core: turn divecomputer list into std::vector<>

Since struct divecomputer is now fully C++ (i.e. cleans up
after itself), we can simply turn the list of divecomputers
into an std::vector<>. This makes the code quite a bit simpler,
because the first divecomputer was actually a subobject.

Yes, this makes the common case of a single divecomputer a
little bit less efficient, but it really shouldn't matter.
If it does, we can still write a special std::vector<>-
like container that keeps the first element inline.

This change makes pointers-to-divecomputers not stable.
So always access the divecomputer via its index. As
far as I can tell, most of the code already does this.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-05-27 17:09:48 +02:00 committed by bstoeger
parent e237f29fb2
commit 284582d2e8
54 changed files with 738 additions and 893 deletions

View file

@ -444,7 +444,7 @@ static void cochran_parse_samples(struct dive *dive, const unsigned char *log,
unsigned int ndl = 0;
unsigned int in_deco = 0, deco_ceiling = 0, deco_time = 0;
struct divecomputer *dc = &dive->dc;
struct divecomputer *dc = &dive->dcs[0];
struct sample *sample;
// Initialize stat variables
@ -664,7 +664,7 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod,
#endif
auto dive = std::make_unique<struct dive>();
dc = &dive->dc;
dc = &dive->dcs[0];
unsigned char *log = (buf + 0x4914);

View file

@ -191,7 +191,7 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct
* Next, Time in minutes since 00:00
*/
read_bytes(2);
dt_dive->dc.when = dt_dive->when = (timestamp_t)date_time_to_ssrfc(tmp_4bytes, tmp_2bytes);
dt_dive->dcs[0].when = dt_dive->when = (timestamp_t)date_time_to_ssrfc(tmp_4bytes, tmp_2bytes);
/*
* Now, Locality, 1st byte is long of string, rest is string
@ -239,19 +239,19 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct
read_bytes(1);
switch (tmp_1byte) {
case 1:
dt_dive->dc.surface_pressure.mbar = 1013;
dt_dive->dcs[0].surface_pressure.mbar = 1013;
break;
case 2:
dt_dive->dc.surface_pressure.mbar = 932;
dt_dive->dcs[0].surface_pressure.mbar = 932;
break;
case 3:
dt_dive->dc.surface_pressure.mbar = 828;
dt_dive->dcs[0].surface_pressure.mbar = 828;
break;
case 4:
dt_dive->dc.surface_pressure.mbar = 735;
dt_dive->dcs[0].surface_pressure.mbar = 735;
break;
default:
dt_dive->dc.surface_pressure.mbar = 1013;
dt_dive->dcs[0].surface_pressure.mbar = 1013;
}
/*
@ -259,7 +259,7 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct
*/
read_bytes(2);
if (tmp_2bytes != 0x7FFF)
dt_dive->dc.surfacetime.seconds = (uint32_t) tmp_2bytes * 60;
dt_dive->dcs[0].surfacetime.seconds = (uint32_t) tmp_2bytes * 60;
/*
* Weather, values table, 0 to 6
@ -296,7 +296,7 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct
*/
read_bytes(2);
if (tmp_2bytes != 0x7FFF)
dt_dive->dc.airtemp.mkelvin = C_to_mkelvin((double)(tmp_2bytes / 100));
dt_dive->dcs[0].airtemp.mkelvin = C_to_mkelvin((double)(tmp_2bytes / 100));
/*
* Dive suit, values table, 0 to 6
@ -349,14 +349,14 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct
*/
read_bytes(2);
if (tmp_2bytes != 0x7FFF)
dt_dive->maxdepth.mm = dt_dive->dc.maxdepth.mm = (int32_t)tmp_2bytes * 10;
dt_dive->maxdepth.mm = dt_dive->dcs[0].maxdepth.mm = (int32_t)tmp_2bytes * 10;
/*
* Dive time in minutes.
*/
read_bytes(2);
if (tmp_2bytes != 0x7FFF)
dt_dive->duration.seconds = dt_dive->dc.duration.seconds = (uint32_t)tmp_2bytes * 60;
dt_dive->duration.seconds = dt_dive->dcs[0].duration.seconds = (uint32_t)tmp_2bytes * 60;
/*
* Minimum water temperature in C*100. If unknown, set it to 0K which
@ -364,7 +364,7 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct
*/
read_bytes(2);
if (tmp_2bytes != 0x7fff)
dt_dive->watertemp.mkelvin = dt_dive->dc.watertemp.mkelvin = C_to_mkelvin((double)(tmp_2bytes / 100));
dt_dive->watertemp.mkelvin = dt_dive->dcs[0].watertemp.mkelvin = C_to_mkelvin((double)(tmp_2bytes / 100));
else
dt_dive->watertemp.mkelvin = 0;
@ -404,7 +404,7 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct
if (bit_set(tmp_1byte, 1)) {
taglist_add_tag(&dt_dive->tag_list, strdup("rebreather"));
is_SCR = 1;
dt_dive->dc.divemode = PSCR;
dt_dive->dcs[0].divemode = PSCR;
}
/*
@ -519,7 +519,7 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct
libdc_model = dtrak_prepare_data(tmp_1byte, devdata);
if (!libdc_model)
report_error(translate("gettextFromC", "[Warning] Manual dive # %d\n"), dt_dive->number);
dt_dive->dc.model = copy_string(devdata.model.c_str());
dt_dive->dcs[0].model = copy_string(devdata.model.c_str());
/*
* Air usage, unknown use. Probably allows or deny manually entering gas
@ -561,10 +561,9 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct
* Initialize some dive data not supported by Datatrak/WLog
*/
if (!libdc_model)
dt_dive->dc.deviceid = 0;
dt_dive->dcs[0].deviceid = 0;
else
dt_dive->dc.deviceid = 0xffffffff;
dt_dive->dc.next = NULL;
dt_dive->dcs[0].deviceid = 0xffffffff;
if (!is_SCR && dt_dive->cylinders.nr > 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);

View file

@ -124,9 +124,8 @@ void clear_device_table(struct device_table *device_table)
bool device_used_by_selected_dive(const struct device *dev)
{
for (dive *d: getDiveSelection()) {
struct divecomputer *dc;
for_each_dc (d, dc) {
if (dc->deviceid == dev->deviceId)
for (auto &dc: d->dcs) {
if (dc.deviceid == dev->deviceId)
return true;
}
}

File diff suppressed because it is too large Load diff

View file

@ -10,6 +10,7 @@
#include "picture.h" // TODO: remove
#include <string>
#include <vector>
extern int last_xml_version;
@ -22,6 +23,7 @@ struct dive_trip;
struct full_text_cache;
struct event;
struct trip_table;
struct dive {
struct dive_trip *divetrip = nullptr;
timestamp_t when = 0;
@ -45,7 +47,7 @@ struct dive {
int user_salinity = 0; // water density reflecting a user-specified type
struct tag_entry *tag_list = nullptr;
struct divecomputer dc;
std::vector<divecomputer> dcs; // Attn: pointers to divecomputers are not stable!
int id = 0; // unique ID for this dive
struct picture_table pictures = { };
unsigned char git_id[20] = {};
@ -117,8 +119,10 @@ extern std::string get_dive_country(const struct dive *dive);
extern std::string get_dive_location(const struct dive *dive);
extern unsigned int number_of_computers(const struct dive *dive);
extern struct divecomputer *get_dive_dc(struct dive *dive, int nr);
extern const struct divecomputer *get_dive_dc_const(const struct dive *dive, int nr);
extern const struct divecomputer *get_dive_dc(const struct dive *dive, int nr);
extern timestamp_t dive_endtime(const struct dive *dive);
extern temperature_t dc_airtemp(const struct dive *dive);
extern temperature_t dc_watertemp(const struct dive *dive);
extern void set_git_prefs(const char *prefs);
@ -136,12 +140,6 @@ void split_divecomputer(const struct dive *src, int num, struct dive **out1, str
#define for_each_dive(_i, _x) \
for ((_i) = 0; ((_x) = get_dive(_i)) != NULL; (_i)++)
#define for_each_dc(_dive, _dc) \
for (_dc = &_dive->dc; _dc; _dc = _dc->next)
#define for_each_relevant_dc(_dive, _dc) \
for (_dc = &_dive->dc; _dc; _dc = _dc->next) if (!is_logged(_dive) || !is_dc_planner(_dc))
extern struct dive *get_dive_by_uniq_id(int id);
extern int get_idx_by_uniq_id(int id);
extern bool dive_site_has_gps_location(const struct dive_site *ds);

View file

@ -14,6 +14,7 @@
divecomputer::divecomputer() = default;
divecomputer::~divecomputer() = default;
divecomputer::divecomputer(const divecomputer &) = default;
divecomputer::divecomputer(divecomputer &&) = default;
divecomputer &divecomputer::operator=(const divecomputer &) = default;
@ -229,18 +230,6 @@ int get_depth_at_time(const struct divecomputer *dc, unsigned int time)
return depth;
}
static void free_dc(struct divecomputer *dc)
{
delete dc;
}
/* The first divecomputer is embedded in the dive structure. Ignore it.
* For all remainding dcs in the list, free data and structures. */
void free_dive_dcs(struct divecomputer *dc)
{
STRUCTURED_LIST_FREE(struct divecomputer, dc->next, free_dc);
}
struct sample *prepare_sample(struct divecomputer *dc)
{
if (dc) {
@ -274,12 +263,12 @@ void append_sample(const struct sample &sample, struct divecomputer *dc)
*
* This ignores any surface time in the middle of the dive.
*/
void fixup_dc_duration(struct divecomputer *dc)
void fixup_dc_duration(struct divecomputer &dc)
{
int duration = 0;
int lasttime = 0, lastdepth = 0, depthtime = 0;
for (const auto &sample: dc->samples) {
for (const auto &sample: dc.samples) {
int time = sample.time.seconds;
int depth = sample.depth.mm;
@ -292,48 +281,11 @@ void fixup_dc_duration(struct divecomputer *dc)
lasttime = time;
}
if (duration) {
dc->duration.seconds = duration;
dc->meandepth.mm = (depthtime + duration / 2) / duration;
dc.duration.seconds = duration;
dc.meandepth.mm = (depthtime + duration / 2) / duration;
}
}
/*
* What do the dive computers say the water temperature is?
* (not in the samples, but as dc property for dcs that support that)
*/
unsigned int dc_watertemp(const struct divecomputer *dc)
{
int sum = 0, nr = 0;
do {
if (dc->watertemp.mkelvin) {
sum += dc->watertemp.mkelvin;
nr++;
}
} while ((dc = dc->next) != NULL);
if (!nr)
return 0;
return (sum + nr / 2) / nr;
}
/*
* What do the dive computers say the air temperature is?
*/
unsigned int dc_airtemp(const struct divecomputer *dc)
{
int sum = 0, nr = 0;
do {
if (dc->airtemp.mkelvin) {
sum += dc->airtemp.mkelvin;
nr++;
}
} while ((dc = dc->next) != NULL);
if (!nr)
return 0;
return (sum + nr / 2) / nr;
}
static bool operator<(const event &ev1, const event &ev2)
{
if (ev1.time.seconds < ev2.time.seconds)
@ -399,27 +351,27 @@ void add_extra_data(struct divecomputer *dc, const std::string &key, const std::
* positive for "same dive" and negative for "definitely
* not the same dive"
*/
int match_one_dc(const struct divecomputer *a, const struct divecomputer *b)
int match_one_dc(const struct divecomputer &a, const struct divecomputer &b)
{
/* Not same model? Don't know if matching.. */
if (a->model.empty() || b->model.empty())
if (a.model.empty() || b.model.empty())
return 0;
if (strcasecmp(a->model.c_str(), b->model.c_str()))
if (strcasecmp(a.model.c_str(), b.model.c_str()))
return 0;
/* Different device ID's? Don't know */
if (a->deviceid != b->deviceid)
if (a.deviceid != b.deviceid)
return 0;
/* Do we have dive IDs? */
if (!a->diveid || !b->diveid)
if (!a.diveid || !b.diveid)
return 0;
/*
* If they have different dive ID's on the same
* dive computer, that's a definite "same or not"
*/
return a->diveid == b->diveid && a->when == b->when ? 1 : -1;
return a.diveid == b.diveid && a.when == b.when ? 1 : -1;
}
static const char *planner_dc_name = "planned dive";

View file

@ -43,10 +43,10 @@ struct divecomputer {
std::vector<struct sample> samples;
std::vector<struct event> events;
std::vector<struct extra_data> extra_data;
struct divecomputer *next = nullptr;
divecomputer();
~divecomputer();
divecomputer(const divecomputer &);
divecomputer(divecomputer &&);
divecomputer &operator=(const divecomputer &);
};
@ -54,10 +54,9 @@ struct divecomputer {
extern void fake_dc(struct divecomputer *dc);
extern void free_dc_contents(struct divecomputer *dc);
extern int get_depth_at_time(const struct divecomputer *dc, unsigned int time);
extern void free_dive_dcs(struct divecomputer *dc);
extern struct sample *prepare_sample(struct divecomputer *dc);
extern void append_sample(const struct sample &sample, struct divecomputer *dc);
extern void fixup_dc_duration(struct divecomputer *dc);
extern void fixup_dc_duration(struct divecomputer &dc);
extern unsigned int dc_airtemp(const struct divecomputer *dc);
extern unsigned int dc_watertemp(const struct divecomputer *dc);
extern int add_event_to_dc(struct divecomputer *dc, struct event ev); // event structure is consumed, returns index of inserted event
@ -73,6 +72,6 @@ extern bool is_dc_manually_added_dive(const struct divecomputer *dc);
extern void make_manually_added_dive_dc(struct divecomputer *dc);
/* Check if two dive computer entries are the exact same dive (-1=no/0=maybe/1=yes) */
extern int match_one_dc(const struct divecomputer *a, const struct divecomputer *b);
extern int match_one_dc(const struct divecomputer &a, const struct divecomputer &b);
#endif

View file

@ -118,7 +118,7 @@ static int get_sample_o2(const struct dive *dive, const struct divecomputer *dc,
static int calculate_otu(const struct dive *dive)
{
double otu = 0.0;
const struct divecomputer *dc = &dive->dc;
const struct divecomputer *dc = &dive->dcs[0];
for (auto [psample, sample]: pairwise_range(dc->samples)) {
int t;
int po2i, po2f;
@ -179,7 +179,7 @@ static int calculate_otu(const struct dive *dive)
to the end of the segment, assuming a constant rate of change in po2 (i.e. depth) with time. */
static double calculate_cns_dive(const struct dive *dive)
{
const struct divecomputer *dc = &dive->dc;
const struct divecomputer *dc = &dive->dcs[0];
double cns = 0.0;
double rate;
/* Calculate the CNS for each sample in this dive and sum them */
@ -334,7 +334,7 @@ static double calculate_airuse(const struct dive *dive)
int airuse = 0;
// SAC for a CCR dive does not make sense.
if (dive->dc.divemode == CCR)
if (dive->dcs[0].divemode == CCR)
return 0.0;
for (int i = 0; i < dive->cylinders.nr; i++) {
@ -362,7 +362,7 @@ static double calculate_airuse(const struct dive *dive)
/* this only uses the first divecomputer to calculate the SAC rate */
static int calculate_sac(const struct dive *dive)
{
const struct divecomputer *dc = &dive->dc;
const struct divecomputer *dc = &dive->dcs[0];
double airuse, pressure, sac;
int duration, meandepth;
@ -389,10 +389,10 @@ static int calculate_sac(const struct dive *dive)
/* for now we do this based on the first divecomputer */
static void add_dive_to_deco(struct deco_state *ds, struct dive *dive, bool in_planner)
{
struct divecomputer *dc = &dive->dc;
struct divecomputer *dc = &dive->dcs[0];
gasmix_loop loop(*dive, dive->dc);
divemode_loop loop_d(dive->dc);
gasmix_loop loop(*dive, dive->dcs[0]);
divemode_loop loop_d(dive->dcs[0]);
for (auto [psample, sample]: pairwise_range(dc->samples)) {
int t0 = psample.time.seconds;
int t1 = sample.time.seconds;
@ -601,19 +601,21 @@ void update_cylinder_related_info(struct dive *dive)
}
}
/* Compare a list of dive computers by model name */
static int comp_dc(const struct divecomputer *dc1, const struct divecomputer *dc2)
/* Compare list of dive computers by model name */
static int comp_dc(const struct dive *d1, const struct dive *d2)
{
int cmp;
while (dc1 || dc2) {
if (!dc1)
auto it1 = d1->dcs.begin();
auto it2 = d2->dcs.begin();
while (it1 != d1->dcs.end() || it2 != d2->dcs.end()) {
if (it1 == d1->dcs.end())
return -1;
if (!dc2)
if (it2 == d2->dcs.end())
return 1;
if ((cmp = dc1->model.compare(dc2->model)) != 0)
int cmp = it1->model.compare(it2->model);
if (cmp != 0)
return cmp;
dc1 = dc1->next;
dc2 = dc2->next;
++it1;
++it2;
}
return 0;
}
@ -656,7 +658,7 @@ int comp_dives(const struct dive *a, const struct dive *b)
return -1;
if (a->number > b->number)
return 1;
if ((cmp = comp_dc(&a->dc, &b->dc)) != 0)
if ((cmp = comp_dc(a, b)) != 0)
return cmp;
if (a->id < b->id)
return -1;
@ -1375,15 +1377,13 @@ bool has_dive(unsigned int deviceid, unsigned int diveid)
struct dive *dive;
for_each_dive (i, dive) {
struct divecomputer *dc;
for_each_dc (dive, dc) {
if (dc->deviceid != deviceid)
continue;
if (dc->diveid != diveid)
continue;
return 1;
}
}
return 0;
for (auto &dc: dive->dcs) {
if (dc.deviceid != deviceid)
continue;
if (dc.diveid != diveid)
continue;
return 1;
}
}
return 0;
}

View file

@ -1077,7 +1077,7 @@ bool filter_constraint_match_dive(const filter_constraint &c, const struct dive
case FILTER_CONSTRAINT_PLANNED:
return is_planned(d) != c.negate;
case FILTER_CONSTRAINT_DIVE_MODE:
return check_multiple_choice(c, (int)d->dc.divemode); // should we be smarter and check all DCs?
return check_multiple_choice(c, (int)d->dcs[0].divemode); // should we be smarter and check all DCs?
case FILTER_CONSTRAINT_TAGS:
return has_tags(c, d);
case FILTER_CONSTRAINT_PEOPLE:

View file

@ -118,13 +118,13 @@ static int cobalt_dive(void *param, int, char **data, char **)
/* Cobalt stores the pressures, not the depth */
if (data[6])
state->cur_dive->dc.maxdepth.mm = atoi(data[6]);
state->cur_dive->dcs[0].maxdepth.mm = atoi(data[6]);
if (data[7])
state->cur_dive->dc.duration.seconds = atoi(data[7]);
state->cur_dive->dcs[0].duration.seconds = atoi(data[7]);
if (data[8])
state->cur_dive->dc.surface_pressure.mbar = atoi(data[8]);
state->cur_dive->dcs[0].surface_pressure.mbar = atoi(data[8]);
/*
* TODO: the deviceid hash should be calculated here.
*/
@ -140,8 +140,8 @@ static int cobalt_dive(void *param, int, char **data, char **)
settings_end(state);
if (data[9]) {
state->cur_dive->dc.deviceid = atoi(data[9]);
state->cur_dive->dc.model = "Cobalt import";
state->cur_dive->dcs[0].deviceid = atoi(data[9]);
state->cur_dive->dcs[0].model = "Cobalt import";
}
snprintf(get_buffer, sizeof(get_buffer) - 1, get_cylinder_template, state->cur_dive->number);

View file

@ -418,7 +418,7 @@ int try_to_open_csv(std::string &mem, enum csv_format type, struct divelog *log)
auto dive = std::make_unique<struct dive>();
dive->when = date;
dive->number = atoi(header[1]);
dc = &dive->dc;
dc = &dive->dcs[0];
time = 0;
for (;;) {
@ -511,11 +511,11 @@ int parse_txt_file(const char *filename, const char *csv, struct divelog *log)
auto dive = std::make_unique<struct dive>();
dive->when = utc_mktime(&cur_tm);;
dive->dc.model = "Poseidon MkVI Discovery";
dive->dcs[0].model = "Poseidon MkVI Discovery";
value = parse_mkvi_value(memtxt.data(), "Rig Serial number");
dive->dc.deviceid = atoi(value.c_str());
dive->dc.divemode = CCR;
dive->dc.no_o2sensors = 2;
dive->dcs[0].deviceid = atoi(value.c_str());
dive->dcs[0].divemode = CCR;
dive->dcs[0].no_o2sensors = 2;
cyl.cylinder_use = OXYGEN;
cyl.type.size.mliter = 3000;
@ -547,9 +547,9 @@ int parse_txt_file(const char *filename, const char *csv, struct divelog *log)
std::string value = parse_mkvi_value(lineptr, key.c_str());
if (value.empty())
break;
add_extra_data(&dive->dc, key, value);
add_extra_data(&dive->dcs[0], key, value);
}
dc = &dive->dc;
dc = &dive->dcs[0];
/*
* Read samples from the CSV file. A sample contains all the lines with same timestamp. The CSV file has

View file

@ -212,8 +212,8 @@ static int divinglog_profile(void *param, int, char **data, char **)
* Count the number of o2 sensors
*/
if (!state->cur_dive->dc.no_o2sensors && (state->cur_sample->o2sensor[0].mbar || state->cur_sample->o2sensor[1].mbar || state->cur_sample->o2sensor[2].mbar)) {
state->cur_dive->dc.no_o2sensors = state->cur_sample->o2sensor[0].mbar ? 1 : 0 +
if (!state->cur_dive->dcs[0].no_o2sensors && (state->cur_sample->o2sensor[0].mbar || state->cur_sample->o2sensor[1].mbar || state->cur_sample->o2sensor[2].mbar)) {
state->cur_dive->dcs[0].no_o2sensors = state->cur_sample->o2sensor[0].mbar ? 1 : 0 +
state->cur_sample->o2sensor[1].mbar ? 1 : 0 +
state->cur_sample->o2sensor[2].mbar ? 1 : 0;
}
@ -285,10 +285,10 @@ static int divinglog_dive(void *param, int, char **data, char **)
utf8_string(data[4], &state->cur_dive->notes);
if (data[5])
state->cur_dive->dc.maxdepth.mm = lrint(permissive_strtod(data[5], NULL) * 1000);
state->cur_dive->dcs[0].maxdepth.mm = lrint(permissive_strtod(data[5], NULL) * 1000);
if (data[6])
state->cur_dive->dc.duration.seconds = atoi(data[6]) * 60;
state->cur_dive->dcs[0].duration.seconds = atoi(data[6]) * 60;
if (data[7])
utf8_string(data[7], &state->cur_dive->diveguide);
@ -330,7 +330,7 @@ static int divinglog_dive(void *param, int, char **data, char **)
dc_settings_start(state);
if (data[12]) {
state->cur_dive->dc.model = data[12];
state->cur_dive->dcs[0].model = data[12];
} else {
state->cur_settings.dc.model = "Divinglog import";
}
@ -355,10 +355,10 @@ static int divinglog_dive(void *param, int, char **data, char **)
case '0':
break;
case '1':
state->cur_dive->dc.divemode = PSCR;
state->cur_dive->dcs[0].divemode = PSCR;
break;
case '2':
state->cur_dive->dc.divemode = CCR;
state->cur_dive->dcs[0].divemode = CCR;
break;
}
}
@ -367,9 +367,9 @@ static int divinglog_dive(void *param, int, char **data, char **)
settings_end(state);
if (data[12]) {
state->cur_dive->dc.model = data[12];
state->cur_dive->dcs[0].model = data[12];
} else {
state->cur_dive->dc.model = "Divinglog import";
state->cur_dive->dcs[0].model = "Divinglog import";
}
snprintf(get_buffer, sizeof(get_buffer) - 1, get_profile_template, diveid);

View file

@ -132,14 +132,14 @@ static int seac_dive(void *param, int, char **data, char **)
if (data[6]) {
switch (atoi(data[6])) {
case 1:
state->cur_dive->dc.divemode = OC;
state->cur_dive->dcs[0].divemode = OC;
break;
// Gauge Mode
case 2:
state->cur_dive->dc.divemode = UNDEF_COMP_TYPE;
state->cur_dive->dcs[0].divemode = UNDEF_COMP_TYPE;
break;
case 3:
state->cur_dive->dc.divemode = FREEDIVE;
state->cur_dive->dcs[0].divemode = FREEDIVE;
break;
default:
if (verbose) {
@ -155,7 +155,7 @@ static int seac_dive(void *param, int, char **data, char **)
// 10 = dive duration
if (data[10]) {
state->cur_dive->dc.duration.seconds = atoi(data[10]);
state->cur_dive->dcs[0].duration.seconds = atoi(data[10]);
}
// 8 = water_type
@ -181,7 +181,7 @@ static int seac_dive(void *param, int, char **data, char **)
if (data[11]) {
state->cur_dive->dc.maxdepth.mm = 10 * atoi(data[11]);
state->cur_dive->dcs[0].maxdepth.mm = 10 * atoi(data[11]);
}
// Create sql_stmt type to query DB
@ -205,20 +205,20 @@ static int seac_dive(void *param, int, char **data, char **)
settings_start(state);
dc_settings_start(state);
utf8_string_std(data[1], &state->cur_dive->dc.serial);
utf8_string_std(data[12],&state->cur_dive->dc.fw_version);
state->cur_dive->dc.model = strdup("Seac Action");
utf8_string_std(data[1], &state->cur_dive->dcs[0].serial);
utf8_string_std(data[12],&state->cur_dive->dcs[0].fw_version);
state->cur_dive->dcs[0].model = "Seac Action";
state->cur_dive->dc.deviceid = calculate_string_hash(data[1]);
state->cur_dive->dcs[0].deviceid = calculate_string_hash(data[1]);
add_extra_data(&state->cur_dive->dc, "GF-Lo", (const char*)sqlite3_column_text(sqlstmt, 9));
add_extra_data(&state->cur_dive->dc, "GF-Hi", (const char*)sqlite3_column_text(sqlstmt, 10));
add_extra_data(&state->cur_dive->dcs[0], "GF-Lo", (const char*)sqlite3_column_text(sqlstmt, 9));
add_extra_data(&state->cur_dive->dcs[0], "GF-Hi", (const char*)sqlite3_column_text(sqlstmt, 10));
dc_settings_end(state);
settings_end(state);
if (data[11]) {
state->cur_dive->dc.maxdepth.mm = 10 * atoi(data[11]);
state->cur_dive->dcs[0].maxdepth.mm = 10 * atoi(data[11]);
}
curcyl->gasmix.o2.permille = 10 * sqlite3_column_int(sqlstmt, 4);

View file

@ -214,7 +214,7 @@ static int shearwater_mode(void *param, int, char **data, char **)
struct parser_state *state = (struct parser_state *)param;
if (data[0])
state->cur_dive->dc.divemode = atoi(data[0]) == 0 ? CCR : OC;
state->cur_dive->dcs[0].divemode = atoi(data[0]) == 0 ? CCR : OC;
return 0;
}
@ -249,13 +249,13 @@ static int shearwater_dive(void *param, int, char **data, char **)
/* TODO: verify that metric calculation is correct */
if (data[6])
state->cur_dive->dc.maxdepth.mm = state->metric ? lrint(permissive_strtod(data[6], NULL) * 1000) : feet_to_mm(permissive_strtod(data[6], NULL));
state->cur_dive->dcs[0].maxdepth.mm = state->metric ? lrint(permissive_strtod(data[6], NULL) * 1000) : feet_to_mm(permissive_strtod(data[6], NULL));
if (data[7])
state->cur_dive->dc.duration.seconds = atoi(data[7]) * 60;
state->cur_dive->dcs[0].duration.seconds = atoi(data[7]) * 60;
if (data[8])
state->cur_dive->dc.surface_pressure.mbar = atoi(data[8]);
state->cur_dive->dcs[0].surface_pressure.mbar = atoi(data[8]);
/*
* TODO: the deviceid hash should be calculated here.
*/
@ -285,13 +285,13 @@ static int shearwater_dive(void *param, int, char **data, char **)
if (data[10]) {
switch (atoi(data[10])) {
case 2:
state->cur_dive->dc.model = "Shearwater Petrel/Perdix";
state->cur_dive->dcs[0].model = "Shearwater Petrel/Perdix";
break;
case 4:
state->cur_dive->dc.model = "Shearwater Predator";
state->cur_dive->dcs[0].model = "Shearwater Predator";
break;
default:
state->cur_dive->dc.model = "Shearwater import";
state->cur_dive->dcs[0].model = "Shearwater import";
break;
}
}
@ -379,13 +379,13 @@ static int shearwater_cloud_dive(void *param, int, char **data, char **)
/* TODO: verify that metric calculation is correct */
if (data[6])
state->cur_dive->dc.maxdepth.mm = state->metric ? lrint(permissive_strtod(data[6], NULL) * 1000) : feet_to_mm(permissive_strtod(data[6], NULL));
state->cur_dive->dcs[0].maxdepth.mm = state->metric ? lrint(permissive_strtod(data[6], NULL) * 1000) : feet_to_mm(permissive_strtod(data[6], NULL));
if (data[7])
state->cur_dive->dc.duration.seconds = atoi(data[7]);
state->cur_dive->dcs[0].duration.seconds = atoi(data[7]);
if (data[8])
state->cur_dive->dc.surface_pressure.mbar = atoi(data[8]);
state->cur_dive->dcs[0].surface_pressure.mbar = atoi(data[8]);
/*
* TODO: the deviceid hash should be calculated here.
*/
@ -415,13 +415,13 @@ static int shearwater_cloud_dive(void *param, int, char **data, char **)
if (data[10]) {
switch (atoi(data[10])) {
case 2:
state->cur_dive->dc.model = "Shearwater Petrel/Perdix";
state->cur_dive->dcs[0].model = "Shearwater Petrel/Perdix";
break;
case 4:
state->cur_dive->dc.model = "Shearwater Predator";
state->cur_dive->dcs[0].model = "Shearwater Predator";
break;
default:
state->cur_dive->dc.model = "Shearwater import";
state->cur_dive->dcs[0].model = "Shearwater import";
break;
}
}

View file

@ -191,7 +191,7 @@ static int dm4_dive(void *param, int, char **data, char **)
if (data[3])
state->cur_dive->duration.seconds = atoi(data[3]);
if (data[15])
state->cur_dive->dc.duration.seconds = atoi(data[15]);
state->cur_dive->dcs[0].duration.seconds = atoi(data[15]);
/*
* TODO: the deviceid hash should be calculated here.
@ -208,11 +208,11 @@ static int dm4_dive(void *param, int, char **data, char **)
settings_end(state);
if (data[6])
state->cur_dive->dc.maxdepth.mm = lrint(permissive_strtod(data[6], NULL) * 1000);
state->cur_dive->dcs[0].maxdepth.mm = lrint(permissive_strtod(data[6], NULL) * 1000);
if (data[8])
state->cur_dive->dc.airtemp.mkelvin = C_to_mkelvin(atoi(data[8]));
state->cur_dive->dcs[0].airtemp.mkelvin = C_to_mkelvin(atoi(data[8]));
if (data[9])
state->cur_dive->dc.watertemp.mkelvin = C_to_mkelvin(atoi(data[9]));
state->cur_dive->dcs[0].watertemp.mkelvin = C_to_mkelvin(atoi(data[9]));
/*
* TODO: handle multiple cylinders
@ -237,7 +237,7 @@ static int dm4_dive(void *param, int, char **data, char **)
cylinder_end(state);
if (data[14])
state->cur_dive->dc.surface_pressure.mbar = (atoi(data[14]) * 1000);
state->cur_dive->dcs[0].surface_pressure.mbar = (atoi(data[14]) * 1000);
interval = data[16] ? atoi(data[16]) : 0;
profileBlob = (float *)data[17];
@ -249,7 +249,7 @@ static int dm4_dive(void *param, int, char **data, char **)
if (profileBlob)
state->cur_sample->depth.mm = lrintf(profileBlob[i] * 1000.0f);
else
state->cur_sample->depth.mm = state->cur_dive->dc.maxdepth.mm;
state->cur_sample->depth.mm = state->cur_dive->dcs[0].maxdepth.mm;
if (data[18] && data[18][0])
state->cur_sample->temperature.mkelvin = C_to_mkelvin(tempBlob[i]);
@ -372,7 +372,7 @@ static int dm5_dive(void *param, int, char **data, char **)
if (data[3])
state->cur_dive->duration.seconds = atoi(data[3]);
if (data[15])
state->cur_dive->dc.duration.seconds = atoi(data[15]);
state->cur_dive->dcs[0].duration.seconds = atoi(data[15]);
/*
* TODO: the deviceid hash should be calculated here.
@ -390,28 +390,28 @@ static int dm5_dive(void *param, int, char **data, char **)
settings_end(state);
if (data[6])
state->cur_dive->dc.maxdepth.mm = lrint(permissive_strtod(data[6], NULL) * 1000);
state->cur_dive->dcs[0].maxdepth.mm = lrint(permissive_strtod(data[6], NULL) * 1000);
if (data[8])
state->cur_dive->dc.airtemp.mkelvin = C_to_mkelvin(atoi(data[8]));
state->cur_dive->dcs[0].airtemp.mkelvin = C_to_mkelvin(atoi(data[8]));
if (data[9])
state->cur_dive->dc.watertemp.mkelvin = C_to_mkelvin(atoi(data[9]));
state->cur_dive->dcs[0].watertemp.mkelvin = C_to_mkelvin(atoi(data[9]));
if (data[4]) {
state->cur_dive->dc.deviceid = atoi(data[4]);
state->cur_dive->dcs[0].deviceid = atoi(data[4]);
}
if (data[5])
utf8_string_std(data[5], &state->cur_dive->dc.model);
utf8_string_std(data[5], &state->cur_dive->dcs[0].model);
if (data[25]) {
switch(atoi(data[25])) {
case 1:
state->cur_dive->dc.divemode = OC;
state->cur_dive->dcs[0].divemode = OC;
break;
case 5:
state->cur_dive->dc.divemode = CCR;
state->cur_dive->dcs[0].divemode = CCR;
break;
default:
state->cur_dive->dc.divemode = OC;
state->cur_dive->dcs[0].divemode = OC;
break;
}
}
@ -424,7 +424,7 @@ static int dm5_dive(void *param, int, char **data, char **)
}
if (data[14])
state->cur_dive->dc.surface_pressure.mbar = (atoi(data[14]) / 100);
state->cur_dive->dcs[0].surface_pressure.mbar = (atoi(data[14]) / 100);
interval = data[16] ? atoi(data[16]) : 0;
@ -512,7 +512,7 @@ static int dm5_dive(void *param, int, char **data, char **)
if (profileBlob)
state->cur_sample->depth.mm = lrintf(profileBlob[i] * 1000.0f);
else
state->cur_sample->depth.mm = state->cur_dive->dc.maxdepth.mm;
state->cur_sample->depth.mm = state->cur_dive->dcs[0].maxdepth.mm;
if (data[18] && data[18][0])
state->cur_sample->temperature.mkelvin = C_to_mkelvin(tempBlob[i]);

View file

@ -212,7 +212,7 @@ static dc_status_t parse_gasmixes(device_data_t *devdata, struct dive *dive, dc_
break;
default:
if (dive->dc.divemode == CCR)
if (dive->dcs[0].divemode == CCR)
cyl.cylinder_use = DILUENT;
else
cyl.cylinder_use = OC_GAS;
@ -526,49 +526,43 @@ static dc_status_t parse_samples(device_data_t *, struct divecomputer *dc, dc_pa
return dc_parser_samples_foreach(parser, sample_cb, dc);
}
static int might_be_same_dc(struct divecomputer *a, struct divecomputer *b)
static int might_be_same_dc(const struct divecomputer &a, const struct divecomputer &b)
{
if (a->model.empty() || b->model.empty())
if (a.model.empty() || b.model.empty())
return 1;
if (strcasecmp(a->model.c_str(), b->model.c_str()))
if (strcasecmp(a.model.c_str(), b.model.c_str()))
return 0;
if (!a->deviceid || !b->deviceid)
if (!a.deviceid || !b.deviceid)
return 1;
return a->deviceid == b->deviceid;
return a.deviceid == b.deviceid;
}
static int match_one_dive(struct divecomputer *a, struct dive *dive)
static bool match_one_dive(const struct divecomputer &a, struct dive *dive)
{
struct divecomputer *b = &dive->dc;
/*
* Walk the existing dive computer data,
* see if we have a match (or an anti-match:
* the same dive computer but a different
* dive ID).
*/
do {
int match = match_one_dc(a, b);
if (match)
return match > 0;
b = b->next;
} while (b);
for (auto &b: dive->dcs) {
if (match_one_dc(a, b) > 0)
return true;
}
/* Ok, no exact dive computer match. Does the date match? */
b = &dive->dc;
do {
if (a->when == b->when && might_be_same_dc(a, b))
return 1;
b = b->next;
} while (b);
for (auto &b: dive->dcs) {
if (a.when == b.when && might_be_same_dc(a, b))
return true;
}
return 0;
return false;
}
/*
* Check if this dive already existed before the import
*/
static int find_dive(struct divecomputer *match)
static int find_dive(const struct divecomputer &match)
{
int i;
@ -604,13 +598,13 @@ static void parse_string_field(device_data_t *devdata, struct dive *dive, dc_fie
{
// Our dive ID is the string hash of the "Dive ID" string
if (!strcmp(str->desc, "Dive ID")) {
if (!dive->dc.diveid)
dive->dc.diveid = calculate_string_hash(str->value);
if (!dive->dcs[0].diveid)
dive->dcs[0].diveid = calculate_string_hash(str->value);
return;
}
// This will pick up serial number and firmware data
add_extra_data(&dive->dc, str->desc, str->value);
add_extra_data(&dive->dcs[0], str->desc, str->value);
/* GPS data? */
if (!strncmp(str->desc, "GPS", 3)) {
@ -648,7 +642,7 @@ static dc_status_t libdc_header_parser(dc_parser_t *parser, device_data_t *devda
}
// Our deviceid is the hash of the serial number
dive->dc.deviceid = 0;
dive->dcs[0].deviceid = 0;
if (rc == DC_STATUS_SUCCESS) {
tm.tm_year = dt.year;
@ -657,7 +651,7 @@ static dc_status_t libdc_header_parser(dc_parser_t *parser, device_data_t *devda
tm.tm_hour = dt.hour;
tm.tm_min = dt.minute;
tm.tm_sec = dt.second;
dive->when = dive->dc.when = utc_mktime(&tm);
dive->when = dive->dcs[0].when = utc_mktime(&tm);
}
// Parse the divetime.
@ -671,7 +665,7 @@ static dc_status_t libdc_header_parser(dc_parser_t *parser, device_data_t *devda
return rc;
}
if (rc == DC_STATUS_SUCCESS)
dive->dc.duration.seconds = divetime;
dive->dcs[0].duration.seconds = divetime;
// Parse the maxdepth.
double maxdepth = 0.0;
@ -681,7 +675,7 @@ static dc_status_t libdc_header_parser(dc_parser_t *parser, device_data_t *devda
return rc;
}
if (rc == DC_STATUS_SUCCESS)
dive->dc.maxdepth.mm = lrint(maxdepth * 1000);
dive->dcs[0].maxdepth.mm = lrint(maxdepth * 1000);
// Parse temperatures
double temperature;
@ -697,11 +691,11 @@ static dc_status_t libdc_header_parser(dc_parser_t *parser, device_data_t *devda
if (rc == DC_STATUS_SUCCESS)
switch(i) {
case 0:
dive->dc.airtemp.mkelvin = C_to_mkelvin(temperature);
dive->dcs[0].airtemp.mkelvin = C_to_mkelvin(temperature);
break;
case 1: // we don't distinguish min and max water temp here, so take min if given, max otherwise
case 2:
dive->dc.watertemp.mkelvin = C_to_mkelvin(temperature);
dive->dcs[0].watertemp.mkelvin = C_to_mkelvin(temperature);
break;
}
}
@ -725,16 +719,16 @@ static dc_status_t libdc_header_parser(dc_parser_t *parser, device_data_t *devda
return rc;
}
if (rc == DC_STATUS_SUCCESS) {
dive->dc.salinity = lrint(salinity.density * 10.0);
if (dive->dc.salinity == 0) {
dive->dcs[0].salinity = lrint(salinity.density * 10.0);
if (dive->dcs[0].salinity == 0) {
// sometimes libdivecomputer gives us density values, sometimes just
// a water type and a density of zero; let's make this work as best as we can
switch (salinity.type) {
case DC_WATER_FRESH:
dive->dc.salinity = FRESHWATER_SALINITY;
dive->dcs[0].salinity = FRESHWATER_SALINITY;
break;
default:
dive->dc.salinity = SEAWATER_SALINITY;
dive->dcs[0].salinity = SEAWATER_SALINITY;
break;
}
}
@ -747,7 +741,7 @@ static dc_status_t libdc_header_parser(dc_parser_t *parser, device_data_t *devda
return rc;
}
if (rc == DC_STATUS_SUCCESS)
dive->dc.surface_pressure.mbar = lrint(surface_pressure * 1000.0);
dive->dcs[0].surface_pressure.mbar = lrint(surface_pressure * 1000.0);
// The dive parsing may give us more device information
int idx;
@ -771,17 +765,17 @@ static dc_status_t libdc_header_parser(dc_parser_t *parser, device_data_t *devda
if (rc == DC_STATUS_SUCCESS)
switch(divemode) {
case DC_DIVEMODE_FREEDIVE:
dive->dc.divemode = FREEDIVE;
dive->dcs[0].divemode = FREEDIVE;
break;
case DC_DIVEMODE_GAUGE:
case DC_DIVEMODE_OC: /* Open circuit */
dive->dc.divemode = OC;
dive->dcs[0].divemode = OC;
break;
case DC_DIVEMODE_CCR: /* Closed circuit rebreather*/
dive->dc.divemode = CCR;
dive->dcs[0].divemode = CCR;
break;
case DC_DIVEMODE_SCR: /* Semi-closed circuit rebreather */
dive->dc.divemode = PSCR;
dive->dcs[0].divemode = PSCR;
break;
}
@ -821,8 +815,8 @@ static int dive_cb(const unsigned char *data, unsigned int size,
auto dive = std::make_unique<struct dive>();
// Fill in basic fields
dive->dc.model = devdata->model;
dive->dc.diveid = calculate_diveid(fingerprint, fsize);
dive->dcs[0].model = devdata->model;
dive->dcs[0].diveid = calculate_diveid(fingerprint, fsize);
// Parse the dive's header data
rc = libdc_header_parser (parser, devdata, dive.get());
@ -832,7 +826,7 @@ static int dive_cb(const unsigned char *data, unsigned int size,
}
// Initialize the sample data.
rc = parse_samples(devdata, &dive->dc, parser);
rc = parse_samples(devdata, &dive->dcs[0], parser);
if (rc != DC_STATUS_SUCCESS) {
download_error(translate("gettextFromC", "Error parsing the samples: %s"), errmsg(rc));
goto error_exit;
@ -850,32 +844,32 @@ static int dive_cb(const unsigned char *data, unsigned int size,
devdata->fingerprint = (unsigned char *)calloc(fsize, 1);
if (devdata->fingerprint) {
devdata->fsize = fsize;
devdata->fdeviceid = dive->dc.deviceid;
devdata->fdiveid = dive->dc.diveid;
devdata->fdeviceid = dive->dcs[0].deviceid;
devdata->fdiveid = dive->dcs[0].diveid;
memcpy(devdata->fingerprint, fingerprint, fsize);
}
}
/* If we already saw this dive, abort. */
if (!devdata->force_download && find_dive(&dive->dc)) {
if (!devdata->force_download && find_dive(dive->dcs[0])) {
std::string date_string = get_dive_date_c_string(dive->when);
dev_info(devdata, translate("gettextFromC", "Already downloaded dive at %s"), date_string.c_str());
return false;
}
/* Various libdivecomputer interface fixups */
if (dive->dc.airtemp.mkelvin == 0 && first_temp_is_air && !dive->dc.samples.empty()) {
dive->dc.airtemp = dive->dc.samples[0].temperature;
dive->dc.samples[0].temperature.mkelvin = 0;
if (dive->dcs[0].airtemp.mkelvin == 0 && first_temp_is_air && !dive->dcs[0].samples.empty()) {
dive->dcs[0].airtemp = dive->dcs[0].samples[0].temperature;
dive->dcs[0].samples[0].temperature.mkelvin = 0;
}
/* special case for bug in Tecdiving DiveComputer.eu
* often the first sample has a water temperature of 0C, followed by the correct
* temperature in the next sample */
if (dive->dc.model == "Tecdiving DiveComputer.eu" && !dive->dc.samples.empty() &&
dive->dc.samples[0].temperature.mkelvin == ZERO_C_IN_MKELVIN &&
dive->dc.samples[1].temperature.mkelvin > dive->dc.samples[0].temperature.mkelvin)
dive->dc.samples[0].temperature.mkelvin = dive->dc.samples[1].temperature.mkelvin;
if (dive->dcs[0].model == "Tecdiving DiveComputer.eu" && !dive->dcs[0].samples.empty() &&
dive->dcs[0].samples[0].temperature.mkelvin == ZERO_C_IN_MKELVIN &&
dive->dcs[0].samples[1].temperature.mkelvin > dive->dcs[0].samples[0].temperature.mkelvin)
dive->dcs[0].samples[0].temperature.mkelvin = dive->dcs[0].samples[1].temperature.mkelvin;
record_dive_to_table(dive.release(), devdata->log->dives.get());
return true;
@ -1593,7 +1587,7 @@ dc_status_t libdc_buffer_parser(struct dive *dive, device_data_t *data, unsigned
report_error("Error parsing the dive header data. Dive # %d: %s", dive->number, errmsg(rc));
}
}
rc = dc_parser_samples_foreach (parser, sample_cb, &dive->dc);
rc = dc_parser_samples_foreach (parser, sample_cb, &dive->dcs[0]);
if (rc != DC_STATUS_SUCCESS) {
report_error("Error parsing the sample data. Dive # %d: %s", dive->number, errmsg(rc));
dc_parser_destroy (parser);

View file

@ -143,7 +143,7 @@ static void parse_dives(int log_version, const unsigned char *buf, unsigned int
int i;
auto dive = std::make_unique<struct dive>();
memset(&sensor_ids, 0, sizeof(sensor_ids));
dc = &dive->dc;
dc = &dive->dcs[0];
/* Just the main cylinder until we can handle the buddy cylinder porperly */
for (i = 0; i < 1; i++) {

View file

@ -1643,15 +1643,12 @@ static git_blob *git_tree_entry_blob(git_repository *repo, const git_tree_entry
static struct divecomputer *create_new_dc(struct dive *dive)
{
struct divecomputer *dc = &dive->dc;
struct divecomputer *dc = &dive->dcs.back();
while (dc->next)
dc = dc->next;
/* Did we already fill that in? */
if (!dc->samples.empty() || !dc->model.empty() || dc->when) {
struct divecomputer *newdc = new divecomputer;
dc->next = newdc;
dc = newdc;
dive->dcs.emplace_back();
dc = &dive->dcs.back();
}
dc->when = dive->when;
dc->duration = dive->duration;

View file

@ -152,7 +152,7 @@ void ostctools_import(const char *file, struct divelog *log)
return;
}
std::string tmp = devdata.vendor + " " + devdata.model + " (Imported from OSTCTools)";
ostcdive->dc.model = tmp.c_str();
ostcdive->dcs[0].model = tmp;
// Parse the dive data
rc = libdc_buffer_parser(ostcdive.get(), &devdata, buffer.data(), i + 1);
@ -161,14 +161,14 @@ void ostctools_import(const char *file, struct divelog *log)
// Serial number is not part of the header nor the profile, so libdc won't
// catch it. If Serial is part of the extra_data, and set to zero, replace it.
ostcdive->dc.serial = std::to_string(serial);
ostcdive->dcs[0].serial = std::to_string(serial);
auto it = find_if(ostcdive->dc.extra_data.begin(), ostcdive->dc.extra_data.end(),
auto it = find_if(ostcdive->dcs[0].extra_data.begin(), ostcdive->dcs[0].extra_data.end(),
[](auto &ed) { return ed.key == "Serial"; });
if (it != ostcdive->dc.extra_data.end() && it->value == "0")
it->value = ostcdive->dc.serial.c_str();
else if (it == ostcdive->dc.extra_data.end())
add_extra_data(&ostcdive->dc, "Serial", ostcdive->dc.serial);
if (it != ostcdive->dcs[0].extra_data.end() && it->value == "0")
it->value = ostcdive->dcs[0].serial.c_str();
else if (it == ostcdive->dcs[0].extra_data.end())
add_extra_data(&ostcdive->dcs[0], "Serial", ostcdive->dcs[0].serial);
record_dive_to_table(ostcdive.release(), log->dives.get());
sort_dive_table(log->dives.get());

View file

@ -1014,9 +1014,9 @@ static int divinglog_dive_match(struct dive *dive, const char *name, char *buf,
}
return MATCH_STATE("divedate", divedate, &dive->when) ||
MATCH_STATE("entrytime", divetime, &dive->when) ||
MATCH("divetime", duration, &dive->dc.duration) ||
MATCH_STATE("depth", depth, &dive->dc.maxdepth) ||
MATCH_STATE("depthavg", depth, &dive->dc.meandepth) ||
MATCH("divetime", duration, &dive->dcs[0].duration) ||
MATCH_STATE("depth", depth, &dive->dcs[0].maxdepth) ||
MATCH_STATE("depthavg", depth, &dive->dcs[0].meandepth) ||
MATCH("comments", utf8_string, &dive->notes) ||
MATCH("names.buddy", utf8_string, &dive->buddy) ||
MATCH("name.country", utf8_string_std, &state->country) ||
@ -1082,8 +1082,8 @@ uddf_datedata(min, 0)
static int uddf_dive_match(struct dive *dive, const char *name, char *buf, struct parser_state *state)
{
return MATCH_STATE("datetime", uddf_datetime, &dive->when) ||
MATCH("diveduration", duration, &dive->dc.duration) ||
MATCH_STATE("greatestdepth", depth, &dive->dc.maxdepth) ||
MATCH("diveduration", duration, &dive->dcs[0].duration) ||
MATCH_STATE("greatestdepth", depth, &dive->dcs[0].maxdepth) ||
MATCH_STATE("year.date", uddf_year, &dive->when) ||
MATCH_STATE("month.date", uddf_mon, &dive->when) ||
MATCH_STATE("day.date", uddf_mday, &dive->when) ||
@ -1269,7 +1269,7 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf, str
* Legacy format note: per-dive depths and duration get saved
* in the first dive computer entry
*/
if (match_dc_data_fields(&dive->dc, name, buf, state))
if (match_dc_data_fields(&dive->dcs[0], name, buf, state))
return;
if (MATCH("filename.picture", utf8_string, &state->cur_picture.filename))

View file

@ -34,7 +34,7 @@ parser_state::~parser_state()
*/
struct divecomputer *get_dc(struct parser_state *state)
{
return state->cur_dc ?: &state->cur_dive->dc;
return state->cur_dc ?: &state->cur_dive->dcs[0];
}
/*
@ -118,7 +118,7 @@ void event_end(struct parser_state *state)
bool is_dive(struct parser_state *state)
{
return state->cur_dive &&
(state->cur_dive->dive_site || state->cur_dive->when || !state->cur_dive->dc.samples.empty());
(state->cur_dive->dive_site || state->cur_dive->when || !state->cur_dive->dcs[0].samples.empty());
}
void reset_dc_info(struct divecomputer *, struct parser_state *state)
@ -264,7 +264,7 @@ void dive_start(struct parser_state *state)
if (state->cur_dive)
return;
state->cur_dive = std::make_unique<dive>();
reset_dc_info(&state->cur_dive->dc, state);
reset_dc_info(&state->cur_dive->dcs[0], state);
memset(&state->cur_tm, 0, sizeof(state->cur_tm));
state->o2pressure_sensor = 1;
}
@ -383,20 +383,12 @@ void sample_end(struct parser_state *state)
void divecomputer_start(struct parser_state *state)
{
struct divecomputer *dc;
/* Start from the previous dive computer */
dc = &state->cur_dive->dc;
while (dc->next)
dc = dc->next;
struct divecomputer *dc = &state->cur_dive->dcs.back();
/* Did we already fill that in? */
if (!dc->samples.empty() || !dc->model.empty() || dc->when) {
struct divecomputer *newdc = new divecomputer;
if (newdc) {
dc->next = newdc;
dc = newdc;
}
state->cur_dive->dcs.emplace_back();
dc = &state->cur_dive->dcs.back();
}
/* .. this is the one we'll use */

View file

@ -128,7 +128,7 @@ static int tissue_at_end(struct deco_state *ds, struct dive *dive, const struct
return 0;
const struct sample *psample = nullptr;
divemode_loop loop(dive->dc);
divemode_loop loop(*dc);
for (auto &sample: dc->samples) {
o2pressure_t setpoint = psample ? psample->setpoint
: sample.setpoint;
@ -809,7 +809,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
plan_add_segment(diveplan, clock - previous_point_time, 0, current_cylinder, po2, false, divemode);
create_dive_from_plan(diveplan, dive, dc, is_planner);
add_plan_to_notes(diveplan, dive, show_disclaimer, error);
fixup_dc_duration(dc);
fixup_dc_duration(*dc);
return false;
}
@ -1091,7 +1091,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
}
create_dive_from_plan(diveplan, dive, dc, is_planner);
add_plan_to_notes(diveplan, dive, show_disclaimer, error);
fixup_dc_duration(dc);
fixup_dc_duration(*dc);
return decodive;
}

View file

@ -452,7 +452,7 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
/* Print the gas consumption next.*/
std::string temp;
if (dive->dc.divemode == CCR)
if (dive->dcs[0].divemode == CCR)
temp = translate("gettextFromC", "Gas consumption (CCR legs excluded):");
else
temp = casprintf_loc("%s %.*f|%.*f%s/min):", translate("gettextFromC", "Gas consumption (based on SAC"),
@ -497,7 +497,7 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
/* not for recreational mode and if no other warning was set before. */
else
if (lastbottomdp && gasidx == lastbottomdp->cylinderid
&& dive->dc.divemode == OC && decoMode(true) != RECREATIONAL) {
&& dive->dcs[0].divemode == OC && decoMode(true) != RECREATIONAL) {
/* Calculate minimum gas volume. */
volume_t mingasv;
mingasv.mliter = lrint(prefs.sacfactor / 100.0 * prefs.problemsolvingtime * prefs.bottomsac
@ -573,8 +573,8 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
bool o2warning_exist = false;
double amb;
divemode_loop loop(dive->dc);
if (dive->dc.divemode != CCR) {
divemode_loop loop(dive->dcs[0]);
if (dive->dcs[0].divemode != CCR) {
while (dp) {
if (dp->time != 0) {
std::string temp;

View file

@ -251,7 +251,6 @@ static void check_setpoint_events(const struct dive *, const struct divecomputer
static void calculate_max_limits_new(const struct dive *dive, const struct divecomputer *given_dc, struct plot_info &pi, bool in_planner)
{
const struct divecomputer *dc = &(dive->dc);
bool seen = false;
bool found_sample_beyond_last_event = false;
int maxdepth = dive->maxdepth.mm;
@ -272,17 +271,14 @@ static void calculate_max_limits_new(const struct dive *dive, const struct divec
minpressure = mbar_end;
}
/* Then do all the samples from all the dive computers */
do {
if (dc == given_dc)
seen = true;
auto process_dc = [&] (const divecomputer &dc) {
int lastdepth = 0;
/* Make sure we can fit all events */
if (!dc->events.empty())
maxtime = std::max(maxtime, dc->events.back().time.seconds);
if (!dc.events.empty())
maxtime = std::max(maxtime, dc.events.back().time.seconds);
for (auto &s: dc->samples) {
for (auto &s: dc.samples) {
int depth = s.depth.mm;
int temperature = s.temperature.mkelvin;
int heartbeat = s.heartbeat;
@ -317,13 +313,16 @@ static void calculate_max_limits_new(const struct dive *dive, const struct divec
}
lastdepth = depth;
}
};
dc = dc->next;
if (dc == NULL && !seen) {
dc = given_dc;
/* Then do all the samples from all the dive computers */
for (auto &dc: dive->dcs) {
if (&dc == given_dc)
seen = true;
}
} while (dc != NULL);
process_dc(dc);
}
if (!seen)
process_dc(*given_dc);
if (minpressure > maxpressure)
minpressure = 0;
@ -659,7 +658,7 @@ static void calculate_sac(const struct dive *dive, const struct divecomputer *dc
}
}
static void populate_secondary_sensor_data(const struct divecomputer *dc, struct plot_info &pi)
static void populate_secondary_sensor_data(const struct divecomputer &dc, struct plot_info &pi)
{
std::vector<int> seen(pi.nr_cylinders, 0);
for (int idx = 0; idx < pi.nr; ++idx)
@ -668,7 +667,7 @@ static void populate_secondary_sensor_data(const struct divecomputer *dc, struct
++seen[c]; // Count instances so we can differentiate a real sensor from just start and end pressure
int idx = 0;
/* We should try to see if it has interesting pressure data here */
for (const auto &sample: dc->samples) {
for (const auto &sample: dc.samples) {
if (idx >= pi.nr)
break;
for (; idx < pi.nr; ++idx) {
@ -708,7 +707,6 @@ static void setup_gas_sensor_pressure(const struct dive *dive, const struct dive
std::vector<int> seen(num_cyl, 0);
std::vector<int> first(num_cyl, 0);
std::vector<int> last(num_cyl, INT_MAX);
const struct divecomputer *secondary;
int prev = explicit_first_cylinder(dive, dc);
prev = prev >= 0 ? prev : 0;
@ -761,8 +759,8 @@ static void setup_gas_sensor_pressure(const struct dive *dive, const struct dive
continue;
/* If it's only mentioned by other dc's, ignore it */
for_each_dc(dive, secondary) {
if (has_gaschange_event(dive, secondary, i)) {
for (auto &secondary: dive->dcs) {
if (has_gaschange_event(dive, &secondary, i)) {
seen[i] = -1;
break;
}
@ -783,12 +781,11 @@ static void setup_gas_sensor_pressure(const struct dive *dive, const struct dive
* and try to see if they have sensor data different from the
* current dive computer (dc).
*/
secondary = &dive->dc;
do {
if (secondary == dc)
for (auto &secondary: dive->dcs) {
if (&secondary == dc)
continue;
populate_secondary_sensor_data(secondary, pi);
} while ((secondary = secondary->next) != NULL);
}
}
/* calculate DECO STOP / TTS / NDL */
@ -1001,7 +998,7 @@ static void calculate_deco_information(struct deco_state *ds, const struct deco_
if (in_planner && !pi.waypoint_above_ceiling &&
entry.depth < max_ceiling - 100 && entry.sec > 0) {
struct dive *non_const_dive = (struct dive *)dive; // cast away const!
add_event(&non_const_dive->dc, entry.sec, SAMPLE_EVENT_CEILING, -1, max_ceiling / 1000,
add_event(&non_const_dive->dcs[0], entry.sec, SAMPLE_EVENT_CEILING, -1, max_ceiling / 1000,
translate("gettextFromC", "planned waypoint above ceiling"));
pi.waypoint_above_ceiling = true;
}
@ -1292,7 +1289,7 @@ struct plot_info create_plot_info_new(const struct dive *dive, const struct dive
debug_print_profiledata(pi);
#endif
pi.meandepth = dive->dc.meandepth.mm;
pi.meandepth = dive->dcs[0].meandepth.mm;
analyze_plot_info(pi);
return pi;
}

View file

@ -119,9 +119,9 @@ static void save_tags(struct membuffer *b, struct tag_entry *tags)
put_string(b, "\n");
}
static void save_extra_data(struct membuffer *b, const struct divecomputer *dc)
static void save_extra_data(struct membuffer *b, const struct divecomputer &dc)
{
for (const auto &ed: dc->extra_data) {
for (const auto &ed: dc.extra_data) {
if (!ed.key.empty() && !ed.value.empty())
put_format(b, "keyvalue \"%s\" \"%s\"\n", ed.key.c_str(), ed.value.c_str());
}
@ -186,34 +186,34 @@ static void save_weightsystem_info(struct membuffer *b, struct dive *dive)
static void save_dive_temperature(struct membuffer *b, struct dive *dive)
{
if (dive->airtemp.mkelvin != dc_airtemp(&dive->dc))
if (dive->airtemp.mkelvin != dc_airtemp(dive).mkelvin)
put_temperature(b, dive->airtemp, "airtemp ", "°C\n");
if (dive->watertemp.mkelvin != dc_watertemp(&dive->dc))
if (dive->watertemp.mkelvin != dc_watertemp(dive).mkelvin)
put_temperature(b, dive->watertemp, "watertemp ", "°C\n");
}
static void save_depths(struct membuffer *b, struct divecomputer *dc)
static void save_depths(struct membuffer *b, const struct divecomputer &dc)
{
put_depth(b, dc->maxdepth, "maxdepth ", "m\n");
put_depth(b, dc->meandepth, "meandepth ", "m\n");
put_depth(b, dc.maxdepth, "maxdepth ", "m\n");
put_depth(b, dc.meandepth, "meandepth ", "m\n");
}
static void save_temperatures(struct membuffer *b, struct divecomputer *dc)
static void save_temperatures(struct membuffer *b, const struct divecomputer &dc)
{
put_temperature(b, dc->airtemp, "airtemp ", "°C\n");
put_temperature(b, dc->watertemp, "watertemp ", "°C\n");
put_temperature(b, dc.airtemp, "airtemp ", "°C\n");
put_temperature(b, dc.watertemp, "watertemp ", "°C\n");
}
static void save_airpressure(struct membuffer *b, struct divecomputer *dc)
static void save_airpressure(struct membuffer *b, const struct divecomputer &dc)
{
put_pressure(b, dc->surface_pressure, "surfacepressure ", "bar\n");
put_pressure(b, dc.surface_pressure, "surfacepressure ", "bar\n");
}
static void save_salinity(struct membuffer *b, struct divecomputer *dc)
static void save_salinity(struct membuffer *b, const struct divecomputer &dc)
{
if (!dc->salinity)
if (!dc.salinity)
return;
put_salinity(b, dc->salinity, "salinity ", "g/l\n");
put_salinity(b, dc.salinity, "salinity ", "g/l\n");
}
static void show_date(struct membuffer *b, timestamp_t when)
@ -367,19 +367,19 @@ static void save_sample(struct membuffer *b, const struct sample &sample, struct
put_format(b, "\n");
}
static void save_samples(struct membuffer *b, struct dive *dive, struct divecomputer *dc)
static void save_samples(struct membuffer *b, struct dive *dive, const struct divecomputer &dc)
{
int o2sensor;
struct sample dummy;
/* Is this a CCR dive with the old-style "o2pressure" sensor? */
o2sensor = legacy_format_o2pressures(dive, dc);
o2sensor = legacy_format_o2pressures(dive, &dc);
if (o2sensor >= 0) {
dummy.sensor[0] = !o2sensor;
dummy.sensor[1] = o2sensor;
}
for (const auto &s: dc->samples)
for (const auto &s: dc.samples)
save_sample(b, s, dummy, o2sensor);
}
@ -403,35 +403,35 @@ static void save_one_event(struct membuffer *b, struct dive *dive, const struct
put_string(b, "\n");
}
static void save_events(struct membuffer *b, struct dive *dive, const struct divecomputer *dc)
static void save_events(struct membuffer *b, struct dive *dive, const struct divecomputer &dc)
{
for (auto &ev: dc->events)
for (auto &ev: dc.events)
save_one_event(b, dive, ev);
}
static void save_dc(struct membuffer *b, struct dive *dive, struct divecomputer *dc)
static void save_dc(struct membuffer *b, struct dive *dive, const struct divecomputer &dc)
{
show_utf8(b, "model ", dc->model.c_str(), "\n");
if (dc->last_manual_time.seconds)
put_duration(b, dc->last_manual_time, "lastmanualtime ", "min\n");
if (dc->deviceid)
put_format(b, "deviceid %08x\n", dc->deviceid);
if (dc->diveid)
put_format(b, "diveid %08x\n", dc->diveid);
if (dc->when && dc->when != dive->when)
show_date(b, dc->when);
if (dc->duration.seconds && dc->duration.seconds != dive->dc.duration.seconds)
put_duration(b, dc->duration, "duration ", "min\n");
if (dc->divemode != OC) {
put_format(b, "dctype %s\n", divemode_text[dc->divemode]);
put_format(b, "numberofoxygensensors %d\n",dc->no_o2sensors);
show_utf8(b, "model ", dc.model.c_str(), "\n");
if (dc.last_manual_time.seconds)
put_duration(b, dc.last_manual_time, "lastmanualtime ", "min\n");
if (dc.deviceid)
put_format(b, "deviceid %08x\n", dc.deviceid);
if (dc.diveid)
put_format(b, "diveid %08x\n", dc.diveid);
if (dc.when && dc.when != dive->when)
show_date(b, dc.when);
if (dc.duration.seconds && dc.duration.seconds != dive->dcs[0].duration.seconds)
put_duration(b, dc.duration, "duration ", "min\n");
if (dc.divemode != OC) {
put_format(b, "dctype %s\n", divemode_text[dc.divemode]);
put_format(b, "numberofoxygensensors %d\n", dc.no_o2sensors);
}
save_depths(b, dc);
save_temperatures(b, dc);
save_airpressure(b, dc);
save_salinity(b, dc);
put_duration(b, dc->surfacetime, "surfacetime ", "min\n");
put_duration(b, dc.surfacetime, "surfacetime ", "min\n");
save_extra_data(b, dc);
save_events(b, dive, dc);
@ -445,8 +445,8 @@ static void save_dc(struct membuffer *b, struct dive *dive, struct divecomputer
static void create_dive_buffer(struct dive *dive, struct membuffer *b)
{
pressure_t surface_pressure = un_fixup_surface_pressure(dive);
if (dive->dc.duration.seconds > 0)
put_format(b, "duration %u:%02u min\n", FRACTION_TUPLE(dive->dc.duration.seconds, 60));
if (dive->dcs[0].duration.seconds > 0)
put_format(b, "duration %u:%02u min\n", FRACTION_TUPLE(dive->dcs[0].duration.seconds, 60));
SAVE("rating", rating);
SAVE("visibility", visibility);
SAVE("wavesize", wavesize);
@ -611,7 +611,7 @@ static int blob_insert(git_repository *repo, struct dir *tree, struct membuffer
return ret;
}
static int save_one_divecomputer(git_repository *repo, struct dir *tree, struct dive *dive, struct divecomputer *dc, int idx)
static int save_one_divecomputer(git_repository *repo, struct dir *tree, struct dive *dive, const struct divecomputer &dc, int idx)
{
int ret;
membuffer buf;
@ -659,7 +659,6 @@ static int save_pictures(git_repository *repo, struct dir *dir, struct dive *div
static int save_one_dive(git_repository *repo, struct dir *tree, struct dive *dive, struct tm *tm, bool cached_ok)
{
struct divecomputer *dc;
membuffer buf, name;
struct dir *subdir;
int ret, nr;
@ -696,12 +695,9 @@ static int save_one_dive(git_repository *repo, struct dir *tree, struct dive *di
* computer, use index 0 for that (which disables the index
* generation when naming it).
*/
dc = &dive->dc;
nr = dc->next ? 1 : 0;
do {
nr = dive->dcs.size() > 1 ? 1 : 0;
for (auto &dc: dive->dcs)
save_one_divecomputer(repo, subdir, dive, dc, nr++);
dc = dc->next;
} while (dc);
/* Save the picture data, if any */
save_pictures(repo, subdir, dive);
@ -1132,7 +1128,6 @@ static void create_commit_message(struct membuffer *msg, bool create_empty)
std::string location = get_dive_location(dive);
if (location.empty())
location = "no location";
struct divecomputer *dc = &dive->dc;
const char *sep = "\n";
if (dive->number)
@ -1142,12 +1137,12 @@ static void create_commit_message(struct membuffer *msg, bool create_empty)
if (trip && !empty_string(trip->location) && location != trip->location)
put_format(msg, " (%s)", trip->location);
put_format(msg, "\n");
do {
if (!dc->model.empty()) {
put_format(msg, "%s%s", sep, dc->model.c_str());
for (auto &dc: dive->dcs) {
if (!dc.model.empty()) {
put_format(msg, "%s%s", sep, dc.model.c_str());
sep = ", ";
}
} while ((dc = dc->next) != NULL);
}
put_format(msg, "\n");
}
put_format(msg, "Created by %s\n", subsurface_user_agent().c_str());

View file

@ -52,19 +52,18 @@ static void save_photos(struct membuffer *b, const char *photos_dir, const struc
static void write_divecomputers(struct membuffer *b, const struct dive *dive)
{
put_string(b, "\"divecomputers\":[");
const struct divecomputer *dc;
const char *separator = "";
for_each_dc (dive, dc) {
for (auto &dc: dive->dcs) {
put_string(b, separator);
separator = ", ";
put_format(b, "{");
write_attribute(b, "model", dc->model.c_str(), ", ");
if (dc->deviceid)
put_format(b, "\"deviceid\":\"%08x\", ", dc->deviceid);
write_attribute(b, "model", dc.model.c_str(), ", ");
if (dc.deviceid)
put_format(b, "\"deviceid\":\"%08x\", ", dc.deviceid);
else
put_string(b, "\"deviceid\":\"--\", ");
if (dc->diveid)
put_format(b, "\"diveid\":\"%08x\" ", dc->diveid);
if (dc.diveid)
put_format(b, "\"diveid\":\"%08x\" ", dc.diveid);
else
put_string(b, "\"diveid\":\"--\" ");
put_format(b, "}");
@ -82,7 +81,7 @@ static void write_dive_status(struct membuffer *b, const struct dive *dive)
static void put_HTML_bookmarks(struct membuffer *b, const struct dive *dive)
{
const char *separator = "\"events\":[";
for (const auto &ev: dive->dc.events) {
for (const auto &ev: dive->dcs[0].events) {
put_string(b, separator);
separator = ", ";
put_string(b, "{\"name\":\"");
@ -172,14 +171,14 @@ static void put_cylinder_HTML(struct membuffer *b, const struct dive *dive)
static void put_HTML_samples(struct membuffer *b, const struct dive *dive)
{
put_format(b, "\"maxdepth\":%d,", dive->dc.maxdepth.mm);
put_format(b, "\"duration\":%d,", dive->dc.duration.seconds);
put_format(b, "\"maxdepth\":%d,", dive->dcs[0].maxdepth.mm);
put_format(b, "\"duration\":%d,", dive->dcs[0].duration.seconds);
if (dive->dc.samples.empty())
if (dive->dcs[0].samples.empty())
return;
const char *separator = "\"samples\":[";
for (auto &s: dive->dc.samples) {
for (auto &s: dive->dcs[0].samples) {
put_format(b, "%s[%d,%d,%d,%d]", separator, s.time.seconds, s.depth.mm, s.pressure[0].mbar, s.temperature.mkelvin);
separator = ", ";
}

View file

@ -210,7 +210,7 @@ static void save_profiles_buffer(struct membuffer *b, bool select_only)
for_each_dive(i, dive) {
if (select_only && !dive->selected)
continue;
plot_info pi = create_plot_info_new(dive, &dive->dc, planner_deco_state);
plot_info pi = create_plot_info_new(dive, &dive->dcs[0], planner_deco_state);
put_headers(b, pi.nr_cylinders);
for (int i = 0; i < pi.nr; i++)
@ -223,7 +223,7 @@ void save_subtitles_buffer(struct membuffer *b, struct dive *dive, int offset, i
{
struct deco_state *planner_deco_state = NULL;
plot_info pi = create_plot_info_new(dive, &dive->dc, planner_deco_state);
plot_info pi = create_plot_info_new(dive, &dive->dcs[0], planner_deco_state);
put_format(b, "[Script Info]\n");
put_format(b, "; Script generated by Subsurface %s\n", subsurface_canonical_version());

View file

@ -116,13 +116,13 @@ static void save_dive_temperature(struct membuffer *b, struct dive *dive)
{
if (!dive->airtemp.mkelvin && !dive->watertemp.mkelvin)
return;
if (dive->airtemp.mkelvin == dc_airtemp(&dive->dc) && dive->watertemp.mkelvin == dc_watertemp(&dive->dc))
if (dive->airtemp.mkelvin == dc_airtemp(dive).mkelvin && dive->watertemp.mkelvin == dc_watertemp(dive).mkelvin)
return;
put_string(b, " <divetemperature");
if (dive->airtemp.mkelvin != dc_airtemp(&dive->dc))
if (dive->airtemp.mkelvin != dc_airtemp(dive).mkelvin)
put_temperature(b, dive->airtemp, " air='", " C'");
if (dive->watertemp.mkelvin != dc_watertemp(&dive->dc))
if (dive->watertemp.mkelvin != dc_watertemp(dive).mkelvin)
put_temperature(b, dive->watertemp, " water='", " C'");
put_string(b, "/>\n");
}
@ -447,7 +447,7 @@ static void save_dc(struct membuffer *b, struct dive *dive, struct divecomputer
put_format(b, " diveid='%08x'", dc->diveid);
if (dc->when && dc->when != dive->when)
show_date(b, dc->when);
if (dc->duration.seconds && dc->duration.seconds != dive->dc.duration.seconds)
if (dc->duration.seconds && dc->duration.seconds != dive->dcs[0].duration.seconds)
put_duration(b, dc->duration, " duration='", " min'");
if (dc->divemode != OC) {
int i = (int)dc->divemode;
@ -490,7 +490,6 @@ static void save_picture(struct membuffer *b, struct picture *pic)
void save_one_dive_to_mb(struct membuffer *b, struct dive *dive, bool anonymize)
{
struct divecomputer *dc;
pressure_t surface_pressure = un_fixup_surface_pressure(dive);
put_string(b, "<dive");
@ -530,9 +529,9 @@ void save_one_dive_to_mb(struct membuffer *b, struct dive *dive, bool anonymize)
show_date(b, dive->when);
if (surface_pressure.mbar)
put_pressure(b, surface_pressure, " airpressure='", " bar'");
if (dive->dc.duration.seconds > 0)
if (dive->dcs[0].duration.seconds > 0)
put_format(b, " duration='%u:%02u min'>\n",
FRACTION_TUPLE(dive->dc.duration.seconds, 60));
FRACTION_TUPLE(dive->dcs[0].duration.seconds, 60));
else
put_format(b, ">\n");
save_overview(b, dive, anonymize);
@ -540,8 +539,8 @@ void save_one_dive_to_mb(struct membuffer *b, struct dive *dive, bool anonymize)
save_weightsystem_info(b, dive);
save_dive_temperature(b, dive);
/* Save the dive computer data */
for_each_dc(dive, dc)
save_dc(b, dive, dc);
for (auto &dc: dive->dcs)
save_dc(b, dive, &dc);
FOR_EACH_PICTURE(dive)
save_picture(b, picture);
put_format(b, "</dive>\n");

View file

@ -151,8 +151,8 @@ stats_summary calculate_stats_summary(bool selected_only)
out.stats_by_type[0].selection_size++;
process_dive(dp, out.stats_by_type[0]);
process_dive(dp, out.stats_by_type[dp->dc.divemode + 1]);
out.stats_by_type[dp->dc.divemode + 1].selection_size++;
process_dive(dp, out.stats_by_type[dp->dcs[0].divemode + 1]);
out.stats_by_type[dp->dcs[0].divemode + 1].selection_size++;
/* stats_by_depth[0] is all the dives combined */
out.stats_by_depth[0].selection_size++;
@ -273,7 +273,6 @@ bool has_gaschange_event(const struct dive *dive, const struct divecomputer *dc,
bool is_cylinder_used(const struct dive *dive, int idx)
{
const struct divecomputer *dc;
cylinder_t *cyl;
if (idx < 0 || idx >= dive->cylinders.nr)
return false;
@ -285,10 +284,10 @@ bool is_cylinder_used(const struct dive *dive, int idx)
if ((cyl->sample_start.mbar - cyl->sample_end.mbar) > SOME_GAS)
return true;
for_each_dc(dive, dc) {
if (has_gaschange_event(dive, dc, idx))
for (auto &dc: dive->dcs) {
if (has_gaschange_event(dive, &dc, idx))
return true;
else if (dc->divemode == CCR && idx == get_cylinder_idx_by_use(dive, OXYGEN))
else if (dc.divemode == CCR && idx == get_cylinder_idx_by_use(dive, OXYGEN))
return true;
}
return false;
@ -296,15 +295,12 @@ bool is_cylinder_used(const struct dive *dive, int idx)
bool is_cylinder_prot(const struct dive *dive, int idx)
{
const struct divecomputer *dc;
if (idx < 0 || idx >= dive->cylinders.nr)
return false;
for_each_dc(dive, dc) {
if (has_gaschange_event(dive, dc, idx))
return true;
}
return false;
return std::any_of(dive->dcs.begin(), dive->dcs.end(),
[dive, idx](auto &dc)
{ return has_gaschange_event(dive, &dc, idx); });
}
/* Returns a vector with dive->cylinders.nr entries */

View file

@ -45,7 +45,7 @@ QString formatSac(const dive *d)
QString formatNotes(const dive *d)
{
QString tmp = d->notes ? QString::fromUtf8(d->notes) : QString();
if (is_dc_planner(&d->dc)) {
if (is_dc_planner(&d->dcs[0])) {
QTextDocument notes;
#define _NOTES_BR "&#92n"
tmp.replace("<thead>", "<thead>" _NOTES_BR)

View file

@ -188,15 +188,15 @@ static void uemis_get_weight(std::string_view buffer, weightsystem_t &weight, in
static std::unique_ptr<dive> uemis_start_dive(uint32_t deviceid)
{
auto dive = std::make_unique<struct dive>();
dive->dc.model = "Uemis Zurich";
dive->dc.deviceid = deviceid;
dive->dcs[0].model = "Uemis Zurich";
dive->dcs[0].deviceid = deviceid;
return dive;
}
static struct dive *get_dive_by_uemis_diveid(device_data_t *devdata, uint32_t object_id)
{
for (int i = 0; i < devdata->log->dives->nr; i++) {
if (object_id == devdata->log->dives->dives[i]->dc.diveid)
if (object_id == devdata->log->dives->dives[i]->dcs[0].diveid)
return devdata->log->dives->dives[i];
}
return NULL;
@ -732,21 +732,21 @@ static void parse_tag(struct dive *dive, std::string_view tag, std::string_view
* with the binary data and would just get overwritten */
#if UEMIS_DEBUG & 4
if (tag == "file_content")
report_info("Adding to dive %d : %s = %s\n", dive->dc.diveid, std::string(tag).c_str(), std::string(val).c_str());
report_info("Adding to dive %d : %s = %s\n", dive->dcs[0].diveid, std::string(tag).c_str(), std::string(val).c_str());
#endif
if (tag == "date") {
dive->when = uemis_ts(val);
} else if (tag == "duration") {
uemis_duration(val, dive->dc.duration);
uemis_duration(val, dive->dcs[0].duration);
} else if (tag == "depth") {
uemis_depth(val, dive->dc.maxdepth);
uemis_depth(val, dive->dcs[0].maxdepth);
} else if (tag == "file_content") {
uemis_obj.parse_divelog_binary(val, dive);
} else if (tag == "altitude") {
uemis_get_index(val, dive->dc.surface_pressure.mbar);
uemis_get_index(val, dive->dcs[0].surface_pressure.mbar);
} else if (tag == "f32Weight") {
weightsystem_t ws = empty_weightsystem;
uemis_get_weight(val, ws, dive->dc.diveid);
uemis_get_weight(val, ws, dive->dcs[0].diveid);
add_cloned_weightsystem(&dive->weightsystems, ws);
} else if (tag == "notes") {
uemis_add_string(val, &dive->notes, " ");
@ -774,12 +774,12 @@ static bool uemis_delete_dive(device_data_t *devdata, uint32_t diveid)
{
struct dive *dive = NULL;
if (devdata->log->dives->dives[devdata->log->dives->nr - 1]->dc.diveid == diveid) {
if (devdata->log->dives->dives[devdata->log->dives->nr - 1]->dcs[0].diveid == diveid) {
/* we hit the last one in the array */
dive = devdata->log->dives->dives[devdata->log->dives->nr - 1];
} else {
for (int i = 0; i < devdata->log->dives->nr - 1; i++) {
if (devdata->log->dives->dives[i]->dc.diveid == diveid) {
if (devdata->log->dives->dives[i]->dcs[0].diveid == diveid) {
dive = devdata->log->dives->dives[i];
for (int x = i; x < devdata->log->dives->nr - 1; x++)
devdata->log->dives->dives[i] = devdata->log->dives->dives[x + 1];
@ -902,7 +902,7 @@ static bool process_raw_buffer(device_data_t *devdata, uint32_t deviceid, std::s
// Is log
if (tag == "object_id") {
from_chars(val, max_divenr);
owned_dive->dc.diveid = max_divenr;
owned_dive->dcs[0].diveid = max_divenr;
#if UEMIS_DEBUG % 2
report_info("Adding new dive from log with object_id %d.\n", max_divenr);
#endif
@ -940,10 +940,10 @@ static bool process_raw_buffer(device_data_t *devdata, uint32_t deviceid, std::s
struct dive_site *ds = devdata->log->sites->create("from Uemis"s);
unregister_dive_from_dive_site(non_owned_dive);
ds->add_dive(non_owned_dive);
uemis_obj.mark_divelocation(non_owned_dive->dc.diveid, divespot_id, ds);
uemis_obj.mark_divelocation(non_owned_dive->dcs[0].diveid, divespot_id, ds);
}
#if UEMIS_DEBUG & 2
report_info("Created divesite %d for diveid : %d\n", non_owned_dive->dive_site->uuid, non_owned_dive->dc.diveid);
report_info("Created divesite %d for diveid : %d\n", non_owned_dive->dive_site->uuid, non_owned_dive->dcs[0].diveid);
#endif
} else if (non_owned_dive) {
parse_tag(non_owned_dive, tag, val);
@ -951,7 +951,7 @@ static bool process_raw_buffer(device_data_t *devdata, uint32_t deviceid, std::s
}
}
if (is_log) {
if (owned_dive->dc.diveid)
if (owned_dive->dcs[0].diveid)
record_dive_to_table(owned_dive.release(), devdata->log->dives.get());
else /* partial dive */
return false;
@ -981,16 +981,15 @@ static std::pair<uint32_t, uint32_t> uemis_get_divenr(uint32_t deviceid, struct
for (i = 0; i < table->nr; i++) {
struct dive *d = table->dives[i];
struct divecomputer *dc;
if (!d)
continue;
for_each_dc (d, dc) {
if (dc->model == "Uemis Zurich" &&
(dc->deviceid == 0 || dc->deviceid == 0x7fffffff || dc->deviceid == deviceid)) {
if (dc->diveid > maxdiveid)
maxdiveid = dc->diveid;
if (dc->diveid < mindiveid)
mindiveid = dc->diveid;
for (auto &dc: d->dcs) {
if (dc.model == "Uemis Zurich" &&
(dc.deviceid == 0 || dc.deviceid == 0x7fffffff || dc.deviceid == deviceid)) {
if (dc.diveid > maxdiveid)
maxdiveid = dc.diveid;
if (dc.diveid < mindiveid)
mindiveid = dc.diveid;
}
}
}
@ -1144,9 +1143,9 @@ static bool get_matching_dive(int idx, int &newmax, uemis_mem_status &mem_status
int deleted_files = 0;
int fail_count = 0;
snprintf(log_file_no_to_find, sizeof(log_file_no_to_find), "logfilenr{int{%d", dive->dc.diveid);
snprintf(log_file_no_to_find, sizeof(log_file_no_to_find), "logfilenr{int{%d", dive->dcs[0].diveid);
#if UEMIS_DEBUG & 2
report_info("Looking for dive details to go with dive log id %d\n", dive->dc.diveid);
report_info("Looking for dive details to go with dive log id %d\n", dive->dcs[0].diveid);
#endif
while (!found) {
if (import_thread_cancelled)
@ -1176,9 +1175,9 @@ static bool get_matching_dive(int idx, int &newmax, uemis_mem_status &mem_status
* UEMIS unfortunately deletes dives by deleting the dive details and not the logs. */
#if UEMIS_DEBUG & 2
d_time = get_dive_date_c_string(dive->when);
report_info("Matching dive log id %d from %s with dive details %d\n", dive->dc.diveid, d_time.c_str(), dive_to_read);
report_info("Matching dive log id %d from %s with dive details %d\n", dive->dcs[0].diveid, d_time.c_str(), dive_to_read);
#endif
int divespot_id = uemis_obj.get_divespot_id_by_diveid(dive->dc.diveid);
int divespot_id = uemis_obj.get_divespot_id_by_diveid(dive->dcs[0].diveid);
if (divespot_id >= 0)
get_uemis_divespot(data, mountpath, divespot_id, dive);
@ -1186,13 +1185,13 @@ static bool get_matching_dive(int idx, int &newmax, uemis_mem_status &mem_status
/* in this case we found a deleted file, so let's increment */
#if UEMIS_DEBUG & 2
d_time = get_dive_date_c_string(dive->when);
report_info("TRY matching dive log id %d from %s with dive details %d but details are deleted\n", dive->dc.diveid, d_time.c_str(), dive_to_read);
report_info("TRY matching dive log id %d from %s with dive details %d but details are deleted\n", dive->dcs[0].diveid, d_time.c_str(), dive_to_read);
#endif
deleted_files++;
/* mark this log entry as deleted and cleanup later, otherwise we mess up our array */
dive->hidden_by_filter = true;
#if UEMIS_DEBUG & 2
report_info("Deleted dive from %s, with id %d from table -- newmax is %d\n", d_time.c_str(), dive->dc.diveid, newmax);
report_info("Deleted dive from %s, with id %d from table -- newmax is %d\n", d_time.c_str(), dive->dcs[0].diveid, newmax);
#endif
}
} else {
@ -1200,7 +1199,7 @@ static bool get_matching_dive(int idx, int &newmax, uemis_mem_status &mem_status
size_t pos = mbuf.find("logfilenr");
if (pos != std::string::npos && mbuf.find("act{") != std::string::npos) {
sscanf(mbuf.c_str() + pos, "logfilenr{int{%u", &nr_found);
if (nr_found >= dive->dc.diveid || nr_found == 0) {
if (nr_found >= dive->dcs[0].diveid || nr_found == 0) {
found_above = true;
dive_to_read = dive_to_read - 2;
} else {
@ -1433,7 +1432,7 @@ std::string do_uemis_import(device_data_t *data)
* to see if we have to clean some dead bodies from our download table */
for (int next_table_index = 0; next_table_index < data->log->dives->nr; ) {
if (data->log->dives->dives[next_table_index]->hidden_by_filter)
uemis_delete_dive(data, data->log->dives->dives[next_table_index]->dc.diveid);
uemis_delete_dive(data, data->log->dives->dives[next_table_index]->dcs[0].diveid);
else
next_table_index++;
}

View file

@ -271,7 +271,7 @@ void uemis::event(struct dive *dive, struct divecomputer *dc, struct sample *sam
}
#if UEMIS_DEBUG & 32
printf("%dm:%ds: p_amb_tol:%d surface:%d holdtime:%d holddepth:%d/%d ---> stopdepth:%d stoptime:%d ndl:%d\n",
sample->time.seconds / 60, sample->time.seconds % 60, u_sample->p_amb_tol, dive->dc.surface_pressure.mbar,
sample->time.seconds / 60, sample->time.seconds % 60, u_sample->p_amb_tol, dive->dcs[0].surface_pressure.mbar,
u_sample->hold_time, u_sample->hold_depth, stopdepth, sample->stopdepth.mm, sample->stoptime.seconds, sample->ndl.seconds);
#endif
}
@ -283,17 +283,17 @@ void uemis::parse_divelog_binary(std::string_view base64, struct dive *dive)
{
struct sample *sample = NULL;
uemis_sample *u_sample;
struct divecomputer *dc = &dive->dc;
struct divecomputer *dc = &dive->dcs[0];
int dive_template, gasoffset;
uint8_t active = 0;
auto data = convert_base64(base64);
dive->dc.airtemp.mkelvin = C_to_mkelvin((*(uint16_t *)(data.data() + 45)) / 10.0);
dive->dc.surface_pressure.mbar = *(uint16_t *)(data.data() + 43);
dive->dcs[0].airtemp.mkelvin = C_to_mkelvin((*(uint16_t *)(data.data() + 45)) / 10.0);
dive->dcs[0].surface_pressure.mbar = *(uint16_t *)(data.data() + 43);
if (*(uint8_t *)(data.data() + 19))
dive->dc.salinity = SEAWATER_SALINITY; /* avg grams per 10l sea water */
dive->dcs[0].salinity = SEAWATER_SALINITY; /* avg grams per 10l sea water */
else
dive->dc.salinity = FRESHWATER_SALINITY; /* grams per 10l fresh water */
dive->dcs[0].salinity = FRESHWATER_SALINITY; /* grams per 10l fresh water */
/* this will allow us to find the last dive read so far from this computer */
dc->model = "Uemis Zurich";
@ -353,7 +353,7 @@ void uemis::parse_divelog_binary(std::string_view base64, struct dive *dive)
u_sample++;
}
if (sample)
dive->dc.duration.seconds = sample->time.seconds - 1;
dive->dcs[0].duration.seconds = sample->time.seconds - 1;
/* get data from the footer */
add_extra_data(dc, "FW Version",