core: add constructor/destructor pairs to dive and divecomputer

This allows us to use non-C member variables. Convert a number
of pointers to unique_ptr<>s.

Code in uemis-downloader.cpp had to be refactored, because
it mixed owning and non-owning pointers. Mad.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-05-16 20:11:21 +02:00 committed by bstoeger
parent bfb54aa581
commit cc39f709ce
35 changed files with 289 additions and 308 deletions

View file

@ -411,7 +411,7 @@ AddDive::AddDive(dive *d, bool autogroup, bool newNumber)
currentDive = nullptr; currentDive = nullptr;
// Get an owning pointer to a moved dive. // Get an owning pointer to a moved dive.
OwningDivePtr divePtr(move_dive(d)); std::unique_ptr<dive> divePtr = move_dive(d);
divePtr->selected = false; // If we clone a planned dive, it might have been selected. divePtr->selected = false; // If we clone a planned dive, it might have been selected.
// We have to clear the flag, as selections will be managed // We have to clear the flag, as selections will be managed
// on dive-addition. // on dive-addition.
@ -494,7 +494,7 @@ ImportDives::ImportDives(struct divelog *log, int flags, const QString &source)
// Add dives to the divesToAdd.dives structure // Add dives to the divesToAdd.dives structure
divesToAdd.dives.reserve(dives_to_add.nr); divesToAdd.dives.reserve(dives_to_add.nr);
for (int i = 0; i < dives_to_add.nr; ++i) { for (int i = 0; i < dives_to_add.nr; ++i) {
OwningDivePtr divePtr(dives_to_add.dives[i]); std::unique_ptr<dive> divePtr(dives_to_add.dives[i]);
divePtr->selected = false; // See above in AddDive::AddDive() divePtr->selected = false; // See above in AddDive::AddDive()
dive_trip *trip = divePtr->divetrip; dive_trip *trip = divePtr->divetrip;
divePtr->divetrip = nullptr; // See above in AddDive::AddDive() divePtr->divetrip = nullptr; // See above in AddDive::AddDive()
@ -971,7 +971,7 @@ MergeDives::MergeDives(const QVector <dive *> &dives)
dive_trip *preferred_trip; dive_trip *preferred_trip;
dive_site *preferred_site; dive_site *preferred_site;
OwningDivePtr d(merge_dives(dives[0], dives[1], dives[1]->when - dives[0]->when, false, &preferred_trip, &preferred_site)); std::unique_ptr<dive> d(merge_dives(dives[0], dives[1], dives[1]->when - dives[0]->when, false, &preferred_trip, &preferred_site));
// Currently, the core code selects the dive -> this is not what we want, as // Currently, the core code selects the dive -> this is not what we want, as
// we manually manage the selection post-command. // we manually manage the selection post-command.

View file

@ -15,7 +15,7 @@ namespace Command {
// This helper structure describes a dive that we want to add. // This helper structure describes a dive that we want to add.
struct DiveToAdd { struct DiveToAdd {
OwningDivePtr dive; // Dive to add std::unique_ptr<struct dive> dive; // Dive to add
dive_trip *trip; // Trip the dive belongs to, may be null dive_trip *trip; // Trip the dive belongs to, may be null
dive_site *site; // Site the dive is associated with, may be null dive_site *site; // Site the dive is associated with, may be null
}; };

View file

@ -797,7 +797,6 @@ ReplanDive::ReplanDive(dive *source) : d(current_dive),
when(0), when(0),
maxdepth({0}), maxdepth({0}),
meandepth({0}), meandepth({0}),
dc({ 0 }),
notes(nullptr), notes(nullptr),
surface_pressure({0}), surface_pressure({0}),
duration({0}), duration({0}),
@ -885,8 +884,7 @@ EditProfile::EditProfile(const dive *source, int dcNr, EditProfileType type, int
maxdepth({0}), maxdepth({0}),
meandepth({0}), meandepth({0}),
dcmaxdepth({0}), dcmaxdepth({0}),
duration({0}), duration({0})
dc({ 0 })
{ {
const struct divecomputer *sdc = get_dive_dc_const(source, dcNr); const struct divecomputer *sdc = get_dive_dc_const(source, dcNr);
if (!sdc) if (!sdc)

View file

@ -465,7 +465,7 @@ public:
EditDive(dive *oldDive, dive *newDive, dive_site *createDs, dive_site *editDs, location_t dsLocation); // Takes ownership of newDive EditDive(dive *oldDive, dive *newDive, dive_site *createDs, dive_site *editDs, location_t dsLocation); // Takes ownership of newDive
private: private:
dive *oldDive; // Dive that is going to be overwritten dive *oldDive; // Dive that is going to be overwritten
OwningDivePtr newDive; // New data std::unique_ptr<dive> newDive; // New data
dive_site *newDiveSite; dive_site *newDiveSite;
int changedFields; int changedFields;

View file

@ -606,7 +606,6 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod,
struct dive_table *table) struct dive_table *table)
{ {
unsigned char *buf = (unsigned char *)malloc(size); unsigned char *buf = (unsigned char *)malloc(size);
struct dive *dive;
struct divecomputer *dc; struct divecomputer *dc;
struct tm tm = {0}; struct tm tm = {0};
@ -666,7 +665,7 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod,
puts("\nSample Data\n"); puts("\nSample Data\n");
#endif #endif
dive = alloc_dive(); auto dive = std::make_unique<struct dive>();
dc = &dive->dc; dc = &dive->dc;
unsigned char *log = (buf + 0x4914); unsigned char *log = (buf + 0x4914);
@ -678,7 +677,7 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod,
cylinder_t cyl; cylinder_t cyl;
dc->model = "Gemini"; dc->model = "Gemini";
dc->deviceid = buf[0x18c] * 256 + buf[0x18d]; // serial no dc->deviceid = buf[0x18c] * 256 + buf[0x18d]; // serial no
fill_default_cylinder(dive, &cyl); fill_default_cylinder(dive.get(), &cyl);
cyl.gasmix.o2.permille = (log[CMD_O2_PERCENT] / 256 cyl.gasmix.o2.permille = (log[CMD_O2_PERCENT] / 256
+ log[CMD_O2_PERCENT + 1]) * 10; + log[CMD_O2_PERCENT + 1]) * 10;
cyl.gasmix.he.permille = 0; cyl.gasmix.he.permille = 0;
@ -688,7 +687,7 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod,
dc->deviceid = array_uint32_le(buf + 0x31e); // serial no dc->deviceid = array_uint32_le(buf + 0x31e); // serial no
for (g = 0; g < 2; g++) { for (g = 0; g < 2; g++) {
cylinder_t cyl; cylinder_t cyl;
fill_default_cylinder(dive, &cyl); fill_default_cylinder(dive.get(), &cyl);
cyl.gasmix.o2.permille = (log[CMD_O2_PERCENT + g * 2] / 256 cyl.gasmix.o2.permille = (log[CMD_O2_PERCENT + g * 2] / 256
+ log[CMD_O2_PERCENT + g * 2 + 1]) * 10; + log[CMD_O2_PERCENT + g * 2 + 1]) * 10;
cyl.gasmix.he.permille = 0; cyl.gasmix.he.permille = 0;
@ -731,7 +730,7 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod,
dc->deviceid = array_uint32_le(buf + 0x31e); // serial no dc->deviceid = array_uint32_le(buf + 0x31e); // serial no
for (g = 0; g < 4; g++) { for (g = 0; g < 4; g++) {
cylinder_t cyl; cylinder_t cyl;
fill_default_cylinder(dive, &cyl); fill_default_cylinder(dive.get(), &cyl);
cyl.gasmix.o2.permille = cyl.gasmix.o2.permille =
(log[EMC_O2_PERCENT + g * 2] / 256 (log[EMC_O2_PERCENT + g * 2] / 256
+ log[EMC_O2_PERCENT + g * 2 + 1]) * 10; + log[EMC_O2_PERCENT + g * 2 + 1]) * 10;
@ -778,7 +777,7 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod,
if (sample_pre_offset < sample_end_offset && sample_end_offset != 0xffffffff) if (sample_pre_offset < sample_end_offset && sample_end_offset != 0xffffffff)
sample_size = sample_end_offset - sample_pre_offset; sample_size = sample_end_offset - sample_pre_offset;
cochran_parse_samples(dive, buf + 0x4914, buf + 0x4914 cochran_parse_samples(dive.get(), buf + 0x4914, buf + 0x4914
+ config.logbook_size, sample_size, + config.logbook_size, sample_size,
&duration, &max_depth, &avg_depth, &min_temp); &duration, &max_depth, &avg_depth, &min_temp);
@ -790,7 +789,7 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod,
dc->duration.seconds = duration; dc->duration.seconds = duration;
} }
record_dive_to_table(dive, table); record_dive_to_table(dive.release(), table);
free(buf); free(buf);
} }

View file

@ -702,18 +702,17 @@ int datatrak_import(std::string &mem, std::string &wl_mem, struct divelog *log)
// Sequential parsing. Abort if received NULL from dt_dive_parser. // Sequential parsing. Abort if received NULL from dt_dive_parser.
while ((i < numdives) && (runner < maxbuf)) { while ((i < numdives) && (runner < maxbuf)) {
struct dive *ptdive = alloc_dive(); auto ptdive = std::make_unique<dive>();
runner = dt_dive_parser((unsigned char *)runner, ptdive, log, maxbuf); runner = dt_dive_parser((unsigned char *)runner, ptdive.get(), log, maxbuf);
if (!wl_mem.empty()) if (!wl_mem.empty())
wlog_compl_parser(wl_mem, ptdive, i); wlog_compl_parser(wl_mem, ptdive.get(), i);
if (runner == NULL) { if (runner == NULL) {
report_error("%s", translate("gettextFromC", "Error: no dive")); report_error("%s", translate("gettextFromC", "Error: no dive"));
free(ptdive);
rc = 1; rc = 1;
goto out; goto out;
} else { } else {
record_dive_to_table(ptdive, log->dives.get()); record_dive_to_table(ptdive.release(), log->dives.get());
} }
i++; i++;
} }

View file

@ -40,6 +40,17 @@ const char *divemode_text[] = {"OC", "CCR", "PSCR", "Freedive"};
static double calculate_depth_to_mbarf(int depth, pressure_t surface_pressure, int salinity); static double calculate_depth_to_mbarf(int depth, pressure_t surface_pressure, int salinity);
dive::dive()
{
id = dive_getUniqID();
}
static void free_dive_structures(struct dive *d);
dive::~dive()
{
free_dive_structures(this);
}
/* /*
* The legacy format for sample pressures has a single pressure * The legacy format for sample pressures has a single pressure
* for each sample that can have any sensor, plus a possible * for each sample that can have any sensor, plus a possible
@ -163,18 +174,6 @@ int dive_getUniqID()
return maxId; return maxId;
} }
struct dive *alloc_dive()
{
struct dive *dive;
dive = (struct dive *)malloc(sizeof(*dive));
if (!dive)
exit(1);
memset(dive, 0, sizeof(*dive));
dive->id = dive_getUniqID();
return dive;
}
/* copy an element in a list of dive computer extra data */ /* copy an element in a list of dive computer extra data */
static void copy_extra_data(struct extra_data *sed, struct extra_data *ded) static void copy_extra_data(struct extra_data *sed, struct extra_data *ded)
{ {
@ -208,7 +207,7 @@ static void copy_dc_renumber(struct dive *d, const struct divecomputer *sdc, str
if (!sdc->next) if (!sdc->next)
break; break;
sdc = sdc->next; sdc = sdc->next;
ddc->next = (divecomputer *)calloc(1, sizeof(struct divecomputer)); ddc->next = new divecomputer;
ddc = ddc->next; ddc = ddc->next;
} }
ddc->next = NULL; ddc->next = NULL;
@ -235,12 +234,6 @@ static void free_dive_structures(struct dive *d)
free(d->pictures.pictures); free(d->pictures.pictures);
} }
void free_dive(struct dive *d)
{
free_dive_structures(d);
free(d);
}
/* copy_dive makes duplicates of many components of a dive; /* copy_dive makes duplicates of many components of a dive;
* in order not to leak memory, we need to free those . * in order not to leak memory, we need to free those .
* copy_dive doesn't play with the divetrip and forward/backward pointers * copy_dive doesn't play with the divetrip and forward/backward pointers
@ -250,7 +243,7 @@ void clear_dive(struct dive *d)
if (!d) if (!d)
return; return;
free_dive_structures(d); free_dive_structures(d);
memset(d, 0, sizeof(struct dive)); *d = dive();
} }
/* make a true copy that is independent of the source dive; /* make a true copy that is independent of the source dive;
@ -297,12 +290,11 @@ static void copy_dive_onedc(const struct dive *s, const struct divecomputer *sdc
/* make a clone of the source dive and clean out the source dive; /* make a clone of the source dive and clean out the source dive;
* this allows us to create a dive on the stack and then * this allows us to create a dive on the stack and then
* add it to the divelist. */ * add it to the divelist. */
struct dive *move_dive(struct dive *s) struct std::unique_ptr<dive> move_dive(struct dive *s)
{ {
struct dive *dive = alloc_dive(); auto d = std::make_unique<dive>();
*dive = *s; // so all the pointers in dive point to the things s pointed to std::swap(*s, *d);
memset(s, 0, sizeof(struct dive)); // and now the pointers in s are gone return d;
return dive;
} }
#define CONDITIONAL_COPY_STRING(_component) \ #define CONDITIONAL_COPY_STRING(_component) \
@ -1300,7 +1292,7 @@ struct dive *fixup_dive(struct dive *dive)
const weightsystem_t &ws = dive->weightsystems.weightsystems[i]; const weightsystem_t &ws = dive->weightsystems.weightsystems[i];
add_weightsystem_description(ws); add_weightsystem_description(ws);
} }
/* we should always have a uniq ID as that gets assigned during alloc_dive(), /* we should always have a uniq ID as that gets assigned during dive creation,
* but we want to make sure... */ * but we want to make sure... */
if (!dive->id) if (!dive->id)
dive->id = dive_getUniqID(); dive->id = dive_getUniqID();
@ -2432,7 +2424,7 @@ static void remove_redundant_dc(struct divecomputer *dc, int prefer_downloaded)
if (same_dc(dc, check) || (prefer_downloaded && might_be_same_device(dc, check))) { if (same_dc(dc, check) || (prefer_downloaded && might_be_same_device(dc, check))) {
*p = check->next; *p = check->next;
check->next = NULL; check->next = NULL;
free_dc(check); delete check;
continue; continue;
} }
p = &check->next; p = &check->next;
@ -2502,7 +2494,7 @@ static void interleave_dive_computers(struct dive *d, struct divecomputer *res,
a = a->next; a = a->next;
if (!a) if (!a)
break; break;
res->next = (divecomputer *)calloc(1, sizeof(struct divecomputer)); res->next = new divecomputer;
res = res->next; res = res->next;
} while (res); } while (res);
} }
@ -2542,7 +2534,7 @@ static void join_dive_computers(struct dive *d, struct divecomputer *res,
while (tmp->next) while (tmp->next)
tmp = tmp->next; tmp = tmp->next;
tmp->next = (divecomputer *)calloc(1, sizeof(*tmp)); tmp->next = new divecomputer;
copy_dc_renumber(d, b, tmp->next, cylinders_map_b); copy_dc_renumber(d, b, tmp->next, cylinders_map_b);
remove_redundant_dc(res, prefer_downloaded); remove_redundant_dc(res, prefer_downloaded);
@ -2602,7 +2594,7 @@ bool is_logged(const struct dive *dive)
*/ */
struct dive *merge_dives(const struct dive *a, const struct dive *b, int offset, bool prefer_downloaded, struct dive_trip **trip, struct dive_site **site) struct dive *merge_dives(const struct dive *a, const struct dive *b, int offset, bool prefer_downloaded, struct dive_trip **trip, struct dive_site **site)
{ {
struct dive *res = alloc_dive(); struct dive *res = new dive;
if (offset) { if (offset) {
/* /*
@ -2670,12 +2662,11 @@ struct dive *merge_dives(const struct dive *a, const struct dive *b, int offset,
// copy_dive(), but retaining the new ID for the copied dive // copy_dive(), but retaining the new ID for the copied dive
static struct dive *create_new_copy(const struct dive *from) static struct dive *create_new_copy(const struct dive *from)
{ {
struct dive *to = alloc_dive(); struct dive *to = new dive;
int id;
// alloc_dive() gave us a new ID, we just need to // dive creation gave us a new ID, we just need to
// make sure it's not overwritten. // make sure it's not overwritten.
id = to->id; int id = to->id;
copy_dive(from, to); copy_dive(from, to);
to->id = id; to->id = id;
return to; return to;
@ -3049,11 +3040,10 @@ void set_git_prefs(const char *prefs)
/* clones a dive and moves given dive computer to front */ /* clones a dive and moves given dive computer to front */
struct dive *make_first_dc(const struct dive *d, int dc_number) struct dive *make_first_dc(const struct dive *d, int dc_number)
{ {
struct dive *res;
struct divecomputer *dc, *newdc, *old_dc; struct divecomputer *dc, *newdc, *old_dc;
/* copy the dive */ /* copy the dive */
res = alloc_dive(); dive *res = new dive;
copy_dive(d, res); copy_dive(d, res);
/* make a new unique id, since we still can't handle two equal ids */ /* make a new unique id, since we still can't handle two equal ids */
@ -3092,12 +3082,12 @@ static void delete_divecomputer(struct dive *d, int num)
return; return;
if (num == 0) { if (num == 0) {
/* remove the first one, so copy the second one in place of the first and free the second one /* During our move to C++, copy the divecomputer instead of moving the internals.
* be careful about freeing the no longer needed structures - since we copy things around we can't use free_dc()*/ * Yes, this is "inefficient", but I don't care. Will be removed anyways. */
struct divecomputer *fdc = d->dc.next; struct divecomputer *fdc = d->dc.next;
free_dc_contents(&d->dc); free_dc_contents(&d->dc);
memcpy(&d->dc, fdc, sizeof(struct divecomputer)); copy_dc(fdc, &d->dc);
free(fdc); delete fdc;
} else { } else {
struct divecomputer *pdc = &d->dc; struct divecomputer *pdc = &d->dc;
for (i = 0; i < num - 1 && pdc; i++) for (i = 0; i < num - 1 && pdc; i++)
@ -3105,7 +3095,7 @@ static void delete_divecomputer(struct dive *d, int num)
if (pdc && pdc->next) { if (pdc && pdc->next) {
struct divecomputer *dc = pdc->next; struct divecomputer *dc = pdc->next;
pdc->next = dc->next; pdc->next = dc->next;
free_dc(dc); delete dc;
} }
} }
} }
@ -3113,10 +3103,8 @@ static void delete_divecomputer(struct dive *d, int num)
/* Clone a dive and delete goven dive computer */ /* Clone a dive and delete goven dive computer */
struct dive *clone_delete_divecomputer(const struct dive *d, int dc_number) struct dive *clone_delete_divecomputer(const struct dive *d, int dc_number)
{ {
struct dive *res;
/* copy the dive */ /* copy the dive */
res = alloc_dive(); dive *res = new dive;
copy_dive(d, res); copy_dive(d, res);
/* make a new unique id, since we still can't handle two equal ids */ /* make a new unique id, since we still can't handle two equal ids */
@ -3140,7 +3128,7 @@ void split_divecomputer(const struct dive *src, int num, struct dive **out1, str
if (src && srcdc) { if (src && srcdc) {
// Copy the dive, but only using the selected dive computer // Copy the dive, but only using the selected dive computer
*out2 = alloc_dive(); *out2 = new dive;
copy_dive_onedc(src, srcdc, *out2); copy_dive_onedc(src, srcdc, *out2);
// This will also make fixup_dive() to allocate a new dive id... // This will also make fixup_dive() to allocate a new dive id...

View file

@ -25,37 +25,40 @@ struct full_text_cache;
struct event; struct event;
struct trip_table; struct trip_table;
struct dive { struct dive {
struct dive_trip *divetrip; struct dive_trip *divetrip = nullptr;
timestamp_t when; timestamp_t when = 0;
struct dive_site *dive_site; struct dive_site *dive_site = nullptr;
char *notes; char *notes = nullptr;
char *diveguide, *buddy; char *diveguide = nullptr, *buddy = nullptr;
struct cylinder_table cylinders; struct cylinder_table cylinders = { };
struct weightsystem_table weightsystems; struct weightsystem_table weightsystems = { };
char *suit; char *suit = nullptr;
int number; int number = 0;
int rating; int rating = 0;
int wavesize, current, visibility, surge, chill; /* 0 - 5 star ratings */ int wavesize = 0, current = 0, visibility = 0, surge = 0, chill = 0; /* 0 - 5 star ratings */
int sac, otu, cns, maxcns; int sac = 0, otu = 0, cns = 0, maxcns = 0;
/* Calculated based on dive computer data */ /* Calculated based on dive computer data */
temperature_t mintemp, maxtemp, watertemp, airtemp; temperature_t mintemp, maxtemp, watertemp, airtemp;
depth_t maxdepth, meandepth; depth_t maxdepth, meandepth;
pressure_t surface_pressure; pressure_t surface_pressure;
duration_t duration; duration_t duration;
int salinity; // kg per 10000 l int salinity = 0; // kg per 10000 l
int user_salinity; // water density reflecting a user-specified type int user_salinity = 0; // water density reflecting a user-specified type
struct tag_entry *tag_list; struct tag_entry *tag_list = nullptr;
struct divecomputer dc; struct divecomputer dc;
int id; // unique ID for this dive int id = 0; // unique ID for this dive
struct picture_table pictures; struct picture_table pictures = { };
unsigned char git_id[20]; unsigned char git_id[20] = {};
bool notrip; /* Don't autogroup this dive to a trip */ bool notrip = false; /* Don't autogroup this dive to a trip */
bool selected; bool selected = false;
bool hidden_by_filter; bool hidden_by_filter = false;
struct full_text_cache *full_text; /* word cache for full text search */ struct full_text_cache *full_text = nullptr; /* word cache for full text search */
bool invalid; bool invalid = false;
dive();
~dive();
}; };
/* For the top-level list: an entry is either a dive or a trip */ /* For the top-level list: an entry is either a dive or a trip */
@ -161,13 +164,11 @@ extern void subsurface_console_init();
extern void subsurface_console_exit(); extern void subsurface_console_exit();
extern bool subsurface_user_is_root(); extern bool subsurface_user_is_root();
extern struct dive *alloc_dive();
extern void free_dive(struct dive *);
extern void record_dive_to_table(struct dive *dive, struct dive_table *table); extern void record_dive_to_table(struct dive *dive, struct dive_table *table);
extern void clear_dive(struct dive *dive); extern void clear_dive(struct dive *dive);
extern void copy_dive(const struct dive *s, struct dive *d); extern void copy_dive(const struct dive *s, struct dive *d);
extern void selective_copy_dive(const struct dive *s, struct dive *d, struct dive_components what, bool clear); extern void selective_copy_dive(const struct dive *s, struct dive *d, struct dive_components what, bool clear);
extern struct dive *move_dive(struct dive *s); extern struct std::unique_ptr<dive> move_dive(struct dive *s);
extern int legacy_format_o2pressures(const struct dive *dive, const struct divecomputer *dc); extern int legacy_format_o2pressures(const struct dive *dive, const struct divecomputer *dc);

View file

@ -11,6 +11,15 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
divecomputer::divecomputer()
{
}
divecomputer::~divecomputer()
{
free_dc_contents(this);
}
/* /*
* Good fake dive profiles are hard. * Good fake dive profiles are hard.
* *
@ -234,11 +243,15 @@ int get_depth_at_time(const struct divecomputer *dc, unsigned int time)
} }
/* The first divecomputer is embedded in the dive structure. Free its data but not static void free_dc(struct divecomputer *dc)
* the structure itself. For all remainding dcs in the list, free data *and* structures. */ {
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) void free_dive_dcs(struct divecomputer *dc)
{ {
free_dc_contents(dc);
STRUCTURED_LIST_FREE(struct divecomputer, dc->next, free_dc); STRUCTURED_LIST_FREE(struct divecomputer, dc->next, free_dc);
} }
@ -545,12 +558,6 @@ void free_dc_contents(struct divecomputer *dc)
STRUCTURED_LIST_FREE(struct extra_data, dc->extra_data, free_extra_data); STRUCTURED_LIST_FREE(struct extra_data, dc->extra_data, free_extra_data);
} }
void free_dc(struct divecomputer *dc)
{
free_dc_contents(dc);
free(dc);
}
static const char *planner_dc_name = "planned dive"; static const char *planner_dc_name = "planned dive";
bool is_dc_planner(const struct divecomputer *dc) bool is_dc_planner(const struct divecomputer *dc)

View file

@ -26,25 +26,27 @@ struct sample;
* A deviceid or diveid of zero is assumed to be "no ID". * A deviceid or diveid of zero is assumed to be "no ID".
*/ */
struct divecomputer { struct divecomputer {
timestamp_t when; timestamp_t when = 0;
duration_t duration, surfacetime, last_manual_time; duration_t duration, surfacetime, last_manual_time;
depth_t maxdepth, meandepth; depth_t maxdepth, meandepth;
temperature_t airtemp, watertemp; temperature_t airtemp, watertemp;
pressure_t surface_pressure; pressure_t surface_pressure;
enum divemode_t divemode; // dive computer type: OC(default) or CCR enum divemode_t divemode = OC; // dive computer type: OC(default) or CCR
uint8_t no_o2sensors; // rebreathers: number of O2 sensors used uint8_t no_o2sensors = 0; // rebreathers: number of O2 sensors used
int salinity; // kg per 10000 l int salinity = 0; // kg per 10000 l
const char *model, *serial, *fw_version; const char *model = nullptr, *serial = nullptr, *fw_version = nullptr;
uint32_t deviceid, diveid; uint32_t deviceid = 0, diveid = 0;
int samples, alloc_samples; int samples = 0, alloc_samples = 0;
struct sample *sample; struct sample *sample = nullptr;
struct event *events; struct event *events = nullptr;
struct extra_data *extra_data; struct extra_data *extra_data = nullptr;
struct divecomputer *next; struct divecomputer *next = nullptr;
divecomputer();
~divecomputer();
}; };
extern void fake_dc(struct divecomputer *dc); extern void fake_dc(struct divecomputer *dc);
extern void free_dc(struct divecomputer *dc);
extern void free_dc_contents(struct divecomputer *dc); extern void free_dc_contents(struct divecomputer *dc);
extern enum divemode_t get_current_divemode(const struct divecomputer *dc, int time, const struct event **evp, enum divemode_t *divemode); extern enum divemode_t get_current_divemode(const struct divecomputer *dc, int time, const struct event **evp, enum divemode_t *divemode);
extern int get_depth_at_time(const struct divecomputer *dc, unsigned int time); extern int get_depth_at_time(const struct divecomputer *dc, unsigned int time);

View file

@ -687,6 +687,10 @@ int comp_dives(const struct dive *a, const struct dive *b)
} }
/* Dive table functions */ /* Dive table functions */
static void free_dive(dive *d)
{
delete d;
}
static MAKE_GROW_TABLE(dive_table, struct dive *, dives) static MAKE_GROW_TABLE(dive_table, struct dive *, dives)
MAKE_GET_INSERTION_INDEX(dive_table, struct dive *, dives, dive_less_than) MAKE_GET_INSERTION_INDEX(dive_table, struct dive *, dives, dive_less_than)
MAKE_ADD_TO(dive_table, struct dive *, dives) MAKE_ADD_TO(dive_table, struct dive *, dives)
@ -735,7 +739,7 @@ static void autogroup_dives(struct dive_table *table, struct trip_table *trip_ta
* It simply shrinks the table and frees the trip */ * It simply shrinks the table and frees the trip */
void delete_dive_from_table(struct dive_table *table, int idx) void delete_dive_from_table(struct dive_table *table, int idx)
{ {
free_dive(table->dives[idx]); delete table->dives[idx];
remove_from_dive_table(table, idx); remove_from_dive_table(table, idx);
} }
@ -818,7 +822,7 @@ static void merge_imported_dives(struct dive_table *table)
unregister_dive_from_trip(dive); unregister_dive_from_trip(dive);
/* Overwrite the first of the two dives and remove the second */ /* Overwrite the first of the two dives and remove the second */
free_dive(prev); delete prev;
table->dives[i - 1] = merged; table->dives[i - 1] = merged;
delete_dive_from_table(table, i); delete_dive_from_table(table, i);
@ -909,7 +913,7 @@ static bool merge_dive_tables(struct dive_table *dives_from, struct dive_table *
dive_endtime(dives_to->dives[j - 1]) > dive_to_add->when) { dive_endtime(dives_to->dives[j - 1]) > dive_to_add->when) {
if (try_to_merge_into(dive_to_add, j - 1, dives_to, prefer_imported, if (try_to_merge_into(dive_to_add, j - 1, dives_to, prefer_imported,
dives_to_add, dives_to_remove)) { dives_to_add, dives_to_remove)) {
free_dive(dive_to_add); delete dive_to_add;
last_merged_into = j - 1; last_merged_into = j - 1;
(*num_merged)++; (*num_merged)++;
continue; continue;
@ -922,7 +926,7 @@ static bool merge_dive_tables(struct dive_table *dives_from, struct dive_table *
dive_endtime(dive_to_add) > dives_to->dives[j]->when) { dive_endtime(dive_to_add) > dives_to->dives[j]->when) {
if (try_to_merge_into(dive_to_add, j, dives_to, prefer_imported, if (try_to_merge_into(dive_to_add, j, dives_to, prefer_imported,
dives_to_add, dives_to_remove)) { dives_to_add, dives_to_remove)) {
free_dive(dive_to_add); delete dive_to_add;
last_merged_into = j; last_merged_into = j;
(*num_merged)++; (*num_merged)++;
continue; continue;

View file

@ -181,7 +181,7 @@ static int cobalt_dive(void *param, int, char **data, char **)
if (location && location_site) { if (location && location_site) {
std::string tmp = std::string(location) + " / " + location_site; std::string tmp = std::string(location) + " / " + location_site;
state->log->sites->find_or_create(tmp)->add_dive(state->cur_dive); state->log->sites->find_or_create(tmp)->add_dive(state->cur_dive.get());
} }
free(location); free(location);
free(location_site); free(location_site);

View file

@ -401,7 +401,6 @@ int try_to_open_csv(std::string &mem, enum csv_format type, struct divelog *log)
char *header[8]; char *header[8];
int i, time; int i, time;
timestamp_t date; timestamp_t date;
struct dive *dive;
struct divecomputer *dc; struct divecomputer *dc;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
@ -416,7 +415,7 @@ int try_to_open_csv(std::string &mem, enum csv_format type, struct divelog *log)
if (!date) if (!date)
return 0; return 0;
dive = alloc_dive(); auto dive = std::make_unique<struct dive>();
dive->when = date; dive->when = date;
dive->number = atoi(header[1]); dive->number = atoi(header[1]);
dc = &dive->dc; dc = &dive->dc;
@ -445,7 +444,7 @@ int try_to_open_csv(std::string &mem, enum csv_format type, struct divelog *log)
break; break;
p = end + 1; p = end + 1;
} }
record_dive_to_table(dive, log->dives.get()); record_dive_to_table(dive.release(), log->dives.get());
return 1; return 1;
} }
@ -498,7 +497,6 @@ int parse_txt_file(const char *filename, const char *csv, struct divelog *log)
int prev_time = 0; int prev_time = 0;
cylinder_t cyl; cylinder_t cyl;
struct dive *dive;
struct divecomputer *dc; struct divecomputer *dc;
struct tm cur_tm; struct tm cur_tm;
@ -512,7 +510,7 @@ int parse_txt_file(const char *filename, const char *csv, struct divelog *log)
cur_tm.tm_min = mm; cur_tm.tm_min = mm;
cur_tm.tm_sec = ss; cur_tm.tm_sec = ss;
dive = alloc_dive(); auto dive = std::make_unique<struct dive>();
dive->when = utc_mktime(&cur_tm);; dive->when = utc_mktime(&cur_tm);;
dive->dc.model = strdup("Poseidon MkVI Discovery"); dive->dc.model = strdup("Poseidon MkVI Discovery");
value = parse_mkvi_value(memtxt.data(), "Rig Serial number"); value = parse_mkvi_value(memtxt.data(), "Rig Serial number");
@ -572,10 +570,8 @@ int parse_txt_file(const char *filename, const char *csv, struct divelog *log)
*/ */
auto [memcsv, err] = readfile(csv); auto [memcsv, err] = readfile(csv);
if (err < 0) { if (err < 0)
free_dive(dive);
return report_error(translate("gettextFromC", "Poseidon import failed: unable to read '%s'"), csv); return report_error(translate("gettextFromC", "Poseidon import failed: unable to read '%s'"), csv);
}
lineptr = memcsv.data(); lineptr = memcsv.data();
for (;;) { for (;;) {
struct sample *sample; struct sample *sample;
@ -750,7 +746,7 @@ int parse_txt_file(const char *filename, const char *csv, struct divelog *log)
if (!lineptr || !*lineptr) if (!lineptr || !*lineptr)
break; break;
} }
record_dive_to_table(dive, log->dives.get()); record_dive_to_table(dive.release(), log->dives.get());
return 1; return 1;
} else { } else {
return 0; return 0;

View file

@ -131,7 +131,7 @@ static int divinglog_profile(void *param, int, char **data, char **)
state->cur_sample->pressure[0].mbar = pressure * 100; state->cur_sample->pressure[0].mbar = pressure * 100;
state->cur_sample->rbt.seconds = rbt; state->cur_sample->rbt.seconds = rbt;
if (oldcyl != tank && tank >= 0 && tank < state->cur_dive->cylinders.nr) { if (oldcyl != tank && tank >= 0 && tank < state->cur_dive->cylinders.nr) {
struct gasmix mix = get_cylinder(state->cur_dive, tank)->gasmix; struct gasmix mix = get_cylinder(state->cur_dive.get(), tank)->gasmix;
int o2 = get_o2(mix); int o2 = get_o2(mix);
int he = get_he(mix); int he = get_he(mix);
@ -276,7 +276,7 @@ static int divinglog_dive(void *param, int, char **data, char **)
state->cur_dive->when = (time_t)(atol(data[1])); state->cur_dive->when = (time_t)(atol(data[1]));
if (data[2]) if (data[2])
state->log->sites->find_or_create(std::string(data[2]))->add_dive(state->cur_dive); state->log->sites->find_or_create(std::string(data[2]))->add_dive(state->cur_dive.get());
if (data[3]) if (data[3])
utf8_string(data[3], &state->cur_dive->buddy); utf8_string(data[3], &state->cur_dive->buddy);

View file

@ -70,7 +70,7 @@ static int seac_dive(void *param, int, char **data, char **)
state->cur_dive->number = atoi(data[0]); state->cur_dive->number = atoi(data[0]);
// Create first cylinder // Create first cylinder
cylinder_t *curcyl = get_or_create_cylinder(state->cur_dive, 0); cylinder_t *curcyl = get_or_create_cylinder(state->cur_dive.get(), 0);
// Get time and date // Get time and date
sscanf(data[2], "%d/%d/%2d", &day, &month, &year); sscanf(data[2], "%d/%d/%2d", &day, &month, &year);
@ -241,7 +241,7 @@ static int seac_dive(void *param, int, char **data, char **)
seac_gaschange(state, sqlstmt); seac_gaschange(state, sqlstmt);
lastgas = curgas; lastgas = curgas;
cylnum ^= 1; // Only need to toggle between two cylinders cylnum ^= 1; // Only need to toggle between two cylinders
curcyl = get_or_create_cylinder(state->cur_dive, cylnum); curcyl = get_or_create_cylinder(state->cur_dive.get(), cylnum);
curcyl->gasmix.o2.permille = 10 * sqlite3_column_int(sqlstmt, 4); curcyl->gasmix.o2.permille = 10 * sqlite3_column_int(sqlstmt, 4);
} }
state->cur_sample->stopdepth.mm = 10 * sqlite3_column_int(sqlstmt, 5); state->cur_sample->stopdepth.mm = 10 * sqlite3_column_int(sqlstmt, 5);

View file

@ -61,7 +61,7 @@ static int shearwater_changes(void *param, int columns, char **data, char **)
int index; int index;
bool found = false; bool found = false;
for (index = 0; index < state->cur_dive->cylinders.nr; ++index) { for (index = 0; index < state->cur_dive->cylinders.nr; ++index) {
const cylinder_t *cyl = get_cylinder(state->cur_dive, index); const cylinder_t *cyl = get_cylinder(state->cur_dive.get(), index);
if (cyl->gasmix.o2.permille == o2 && cyl->gasmix.he.permille == he) { if (cyl->gasmix.o2.permille == o2 && cyl->gasmix.he.permille == he) {
found = true; found = true;
break; break;
@ -75,7 +75,7 @@ static int shearwater_changes(void *param, int columns, char **data, char **)
cylinder_end(state); cylinder_end(state);
} }
add_gas_switch_event(state->cur_dive, get_dc(state), state->sample_rate ? atoi(data[0]) / state->sample_rate * 10 : atoi(data[0]), index); add_gas_switch_event(state->cur_dive.get(), get_dc(state), state->sample_rate ? atoi(data[0]) / state->sample_rate * 10 : atoi(data[0]), index);
return 0; return 0;
} }
@ -239,7 +239,7 @@ static int shearwater_dive(void *param, int, char **data, char **)
long int dive_id = atol(data[11]); long int dive_id = atol(data[11]);
if (data[2]) if (data[2])
add_dive_site(data[2], state->cur_dive, state); add_dive_site(data[2], state->cur_dive.get(), state);
if (data[3]) if (data[3])
utf8_string(data[3], &state->cur_dive->buddy); utf8_string(data[3], &state->cur_dive->buddy);
if (data[4]) if (data[4])
@ -369,7 +369,7 @@ static int shearwater_cloud_dive(void *param, int, char **data, char **)
state->sample_rate = 0; state->sample_rate = 0;
if (data[2]) if (data[2])
add_dive_site(data[2], state->cur_dive, state); add_dive_site(data[2], state->cur_dive.get(), state);
if (data[3]) if (data[3])
utf8_string(data[3], &state->cur_dive->buddy); utf8_string(data[3], &state->cur_dive->buddy);
if (data[4]) if (data[4])

View file

@ -809,7 +809,6 @@ static int dive_cb(const unsigned char *data, unsigned int size,
dc_status_t rc; dc_status_t rc;
dc_parser_t *parser = NULL; dc_parser_t *parser = NULL;
device_data_t *devdata = (device_data_t *)userdata; device_data_t *devdata = (device_data_t *)userdata;
struct dive *dive = NULL;
/* reset static data, that is only valid per dive */ /* reset static data, that is only valid per dive */
stoptime = stopdepth = po2 = cns = heartbeat = 0; stoptime = stopdepth = po2 = cns = heartbeat = 0;
@ -825,14 +824,14 @@ static int dive_cb(const unsigned char *data, unsigned int size,
return true; return true;
} }
dive = alloc_dive(); auto dive = std::make_unique<struct dive>();
// Fill in basic fields // Fill in basic fields
dive->dc.model = strdup(devdata->model.c_str()); dive->dc.model = strdup(devdata->model.c_str());
dive->dc.diveid = calculate_diveid(fingerprint, fsize); dive->dc.diveid = calculate_diveid(fingerprint, fsize);
// Parse the dive's header data // Parse the dive's header data
rc = libdc_header_parser (parser, devdata, dive); rc = libdc_header_parser (parser, devdata, dive.get());
if (rc != DC_STATUS_SUCCESS) { if (rc != DC_STATUS_SUCCESS) {
download_error(translate("getextFromC", "Error parsing the header: %s"), errmsg(rc)); download_error(translate("getextFromC", "Error parsing the header: %s"), errmsg(rc));
goto error_exit; goto error_exit;
@ -867,7 +866,6 @@ static int dive_cb(const unsigned char *data, unsigned int size,
if (!devdata->force_download && find_dive(&dive->dc)) { if (!devdata->force_download && find_dive(&dive->dc)) {
std::string date_string = get_dive_date_c_string(dive->when); 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()); dev_info(devdata, translate("gettextFromC", "Already downloaded dive at %s"), date_string.c_str());
free_dive(dive);
return false; return false;
} }
@ -885,14 +883,12 @@ static int dive_cb(const unsigned char *data, unsigned int size,
dive->dc.sample[1].temperature.mkelvin > dive->dc.sample[0].temperature.mkelvin) dive->dc.sample[1].temperature.mkelvin > dive->dc.sample[0].temperature.mkelvin)
dive->dc.sample[0].temperature.mkelvin = dive->dc.sample[1].temperature.mkelvin; dive->dc.sample[0].temperature.mkelvin = dive->dc.sample[1].temperature.mkelvin;
record_dive_to_table(dive, devdata->log->dives.get()); record_dive_to_table(dive.release(), devdata->log->dives.get());
return true; return true;
error_exit: error_exit:
dc_parser_destroy(parser); dc_parser_destroy(parser);
free_dive(dive);
return true; return true;
} }
#ifndef O_BINARY #ifndef O_BINARY

View file

@ -136,20 +136,19 @@ static void parse_dives(int log_version, const unsigned char *buf, unsigned int
unsigned int ptr = 0; unsigned int ptr = 0;
unsigned char model; unsigned char model;
struct dive *dive;
struct divecomputer *dc; struct divecomputer *dc;
struct sample *sample; struct sample *sample;
while (ptr < buf_size) { while (ptr < buf_size) {
int i; int i;
dive = alloc_dive(); auto dive = std::make_unique<struct dive>();
memset(&sensor_ids, 0, sizeof(sensor_ids)); memset(&sensor_ids, 0, sizeof(sensor_ids));
dc = &dive->dc; dc = &dive->dc;
/* Just the main cylinder until we can handle the buddy cylinder porperly */ /* Just the main cylinder until we can handle the buddy cylinder porperly */
for (i = 0; i < 1; i++) { for (i = 0; i < 1; i++) {
cylinder_t cyl; cylinder_t cyl;
fill_default_cylinder(dive, &cyl); fill_default_cylinder(dive.get(), &cyl);
add_cylinder(&dive->cylinders, i, cyl); add_cylinder(&dive->cylinders, i, cyl);
} }
@ -190,7 +189,7 @@ static void parse_dives(int log_version, const unsigned char *buf, unsigned int
/* Store the location only if we have one */ /* Store the location only if we have one */
if (!location.empty()) if (!location.empty())
sites.find_or_create(location)->add_dive(dive); sites.find_or_create(location)->add_dive(dive.get());
ptr += len + 4 + place_len; ptr += len + 4 + place_len;
@ -414,17 +413,12 @@ static void parse_dives(int log_version, const unsigned char *buf, unsigned int
} }
// End dive // End dive
record_dive_to_table(dive, table); record_dive_to_table(dive.release(), table);
dive = NULL; dive = NULL;
// Advance ptr for next dive // Advance ptr for next dive
ptr += ps_ptr + 4; ptr += ps_ptr + 4;
} // while } // while
//DEBUG save_dives("/tmp/test.xml");
// if we bailed out of the loop, the dive hasn't been recorded and dive hasn't been set to NULL
free_dive(dive);
} }
int try_to_open_liquivision(const char *, std::string &mem, struct divelog *log) int try_to_open_liquivision(const char *, std::string &mem, struct divelog *log)

View file

@ -37,7 +37,7 @@ std::string saved_git_id;
struct git_parser_state { struct git_parser_state {
git_repository *repo = nullptr; git_repository *repo = nullptr;
struct divecomputer *active_dc = nullptr; struct divecomputer *active_dc = nullptr;
struct dive *active_dive = nullptr; std::unique_ptr<dive> active_dive;
dive_trip_t *active_trip = nullptr; dive_trip_t *active_trip = nullptr;
std::string fulltext_mode; std::string fulltext_mode;
std::string fulltext_query; std::string fulltext_query;
@ -171,14 +171,14 @@ static int get_hex(const char *line)
static void parse_dive_gps(char *line, struct git_parser_state *state) static void parse_dive_gps(char *line, struct git_parser_state *state)
{ {
location_t location; location_t location;
struct dive_site *ds = get_dive_site_for_dive(state->active_dive); struct dive_site *ds = get_dive_site_for_dive(state->active_dive.get());
parse_location(line, &location); parse_location(line, &location);
if (!ds) { if (!ds) {
ds = state->log->sites->get_by_gps(&location); ds = state->log->sites->get_by_gps(&location);
if (!ds) if (!ds)
ds = state->log->sites->create(std::string(), location); ds = state->log->sites->create(std::string(), location);
ds->add_dive(state->active_dive); ds->add_dive(state->active_dive.get());
} else { } else {
if (dive_site_has_gps_location(ds) && ds->location != location) { if (dive_site_has_gps_location(ds) && ds->location != location) {
std::string coords = printGPSCoordsC(&location); std::string coords = printGPSCoordsC(&location);
@ -219,12 +219,12 @@ static char *get_first_converted_string_c(struct git_parser_state *state)
static void parse_dive_location(char *, struct git_parser_state *state) static void parse_dive_location(char *, struct git_parser_state *state)
{ {
std::string name = get_first_converted_string(state); std::string name = get_first_converted_string(state);
struct dive_site *ds = get_dive_site_for_dive(state->active_dive); struct dive_site *ds = get_dive_site_for_dive(state->active_dive.get());
if (!ds) { if (!ds) {
ds = state->log->sites->get_by_name(name); ds = state->log->sites->get_by_name(name);
if (!ds) if (!ds)
ds = state->log->sites->create(name); ds = state->log->sites->create(name);
ds->add_dive(state->active_dive); ds->add_dive(state->active_dive.get());
} else { } else {
// we already had a dive site linked to the dive // we already had a dive site linked to the dive
if (ds->name.empty()) { if (ds->name.empty()) {
@ -252,7 +252,7 @@ static void parse_dive_notes(char *, struct git_parser_state *state)
{ state->active_dive->notes = get_first_converted_string_c(state); } { state->active_dive->notes = get_first_converted_string_c(state); }
static void parse_dive_divesiteid(char *line, struct git_parser_state *state) static void parse_dive_divesiteid(char *line, struct git_parser_state *state)
{ state->log->sites->get_by_uuid(get_hex(line))->add_dive(state->active_dive); } { state->log->sites->get_by_uuid(get_hex(line))->add_dive(state->active_dive.get()); }
/* /*
* We can have multiple tags. * We can have multiple tags.
@ -684,8 +684,8 @@ static struct sample *new_sample(struct git_parser_state *state)
sample->pressure[0].mbar = 0; sample->pressure[0].mbar = 0;
sample->pressure[1].mbar = 0; sample->pressure[1].mbar = 0;
} else { } else {
sample->sensor[0] = sanitize_sensor_id(state->active_dive, !state->o2pressure_sensor); sample->sensor[0] = sanitize_sensor_id(state->active_dive.get(), !state->o2pressure_sensor);
sample->sensor[1] = sanitize_sensor_id(state->active_dive, state->o2pressure_sensor); sample->sensor[1] = sanitize_sensor_id(state->active_dive.get(), state->o2pressure_sensor);
} }
return sample; return sample;
} }
@ -1392,23 +1392,19 @@ static void finish_active_trip(struct git_parser_state *state)
static void finish_active_dive(struct git_parser_state *state) static void finish_active_dive(struct git_parser_state *state)
{ {
struct dive *dive = state->active_dive; if (state->active_dive)
record_dive_to_table(state->active_dive.release(), state->log->dives.get());
if (dive) {
state->active_dive = NULL;
record_dive_to_table(dive, state->log->dives.get());
}
} }
static void create_new_dive(timestamp_t when, struct git_parser_state *state) static void create_new_dive(timestamp_t when, struct git_parser_state *state)
{ {
state->active_dive = alloc_dive(); state->active_dive = std::make_unique<dive>();
/* We'll fill in more data from the dive file */ /* We'll fill in more data from the dive file */
state->active_dive->when = when; state->active_dive->when = when;
if (state->active_trip) if (state->active_trip)
add_dive_to_trip(state->active_dive, state->active_trip); add_dive_to_trip(state->active_dive.get(), state->active_trip);
} }
static bool validate_date(int yyyy, int mm, int dd) static bool validate_date(int yyyy, int mm, int dd)
@ -1654,9 +1650,7 @@ static struct divecomputer *create_new_dc(struct dive *dive)
dc = dc->next; dc = dc->next;
/* Did we already fill that in? */ /* Did we already fill that in? */
if (dc->samples || dc->model || dc->when) { if (dc->samples || dc->model || dc->when) {
struct divecomputer *newdc = (divecomputer *)calloc(1, sizeof(*newdc)); struct divecomputer *newdc = new divecomputer;
if (!newdc)
return NULL;
dc->next = newdc; dc->next = newdc;
dc = newdc; dc = newdc;
} }
@ -1678,7 +1672,7 @@ static int parse_divecomputer_entry(struct git_parser_state *state, const git_tr
if (!blob) if (!blob)
return report_error("Unable to read divecomputer file"); return report_error("Unable to read divecomputer file");
state->active_dc = create_new_dc(state->active_dive); state->active_dc = create_new_dc(state->active_dive.get());
for_each_line(blob, divecomputer_parser, state); for_each_line(blob, divecomputer_parser, state);
git_blob_free(blob); git_blob_free(blob);
state->active_dc = NULL; state->active_dc = NULL;
@ -1693,12 +1687,11 @@ static int parse_divecomputer_entry(struct git_parser_state *state, const git_tr
*/ */
static int parse_dive_entry(struct git_parser_state *state, const git_tree_entry *entry, const char *suffix) static int parse_dive_entry(struct git_parser_state *state, const git_tree_entry *entry, const char *suffix)
{ {
struct dive *dive = state->active_dive;
git_blob *blob = git_tree_entry_blob(state->repo, entry); git_blob *blob = git_tree_entry_blob(state->repo, entry);
if (!blob) if (!blob)
return report_error("Unable to read dive file"); return report_error("Unable to read dive file");
if (*suffix) if (*suffix)
dive->number = atoi(suffix + 1); state->active_dive->number = atoi(suffix + 1);
clear_weightsystem_table(&state->active_dive->weightsystems); clear_weightsystem_table(&state->active_dive->weightsystems);
state->o2pressure_sensor = 1; state->o2pressure_sensor = 1;
for_each_line(blob, dive_parser, state); for_each_line(blob, dive_parser, state);
@ -1795,7 +1788,7 @@ static int parse_filter_preset(struct git_parser_state *state, const git_tree_en
static int walk_tree_file(const char *root, const git_tree_entry *entry, struct git_parser_state *state) static int walk_tree_file(const char *root, const git_tree_entry *entry, struct git_parser_state *state)
{ {
struct dive *dive = state->active_dive; auto &dive = state->active_dive;
dive_trip_t *trip = state->active_trip; dive_trip_t *trip = state->active_trip;
const char *name = git_tree_entry_name(entry); const char *name = git_tree_entry_name(entry);
if (verbose > 1) if (verbose > 1)
@ -1826,7 +1819,7 @@ static int walk_tree_file(const char *root, const git_tree_entry *entry, struct
return parse_settings_entry(state, entry); return parse_settings_entry(state, entry);
break; break;
} }
report_error("Unknown file %s%s (%p %p)", root, name, dive, trip); report_error("Unknown file %s%s (%p %p)", root, name, dive.get(), trip);
return GIT_WALK_SKIP; return GIT_WALK_SKIP;
} }

View file

@ -48,7 +48,7 @@ void ostctools_import(const char *file, struct divelog *log)
dc_family_t dc_fam; dc_family_t dc_fam;
std::vector<unsigned char> buffer(65536, 0); std::vector<unsigned char> buffer(65536, 0);
unsigned char uc_tmp[2]; unsigned char uc_tmp[2];
OwningDivePtr ostcdive(alloc_dive()); auto ostcdive = std::make_unique<dive>();
dc_status_t rc = DC_STATUS_SUCCESS; dc_status_t rc = DC_STATUS_SUCCESS;
int model, ret, i = 0, c; int model, ret, i = 0, c;
unsigned int serial; unsigned int serial;

View file

@ -9,24 +9,16 @@
#include <memory> #include <memory>
#include <cstdlib> #include <cstdlib>
struct dive;
struct dive_trip; struct dive_trip;
struct dive_site;
struct event;
void free_dive(struct dive *);
void free_trip(struct dive_trip *); void free_trip(struct dive_trip *);
// Classes used to automatically call the appropriate free_*() function for owning pointers that go out of scope. // Classes used to automatically call the appropriate free_*() function for owning pointers that go out of scope.
struct DiveDeleter {
void operator()(dive *d) { free_dive(d); }
};
struct TripDeleter { struct TripDeleter {
void operator()(dive_trip *t) { free_trip(t); } void operator()(dive_trip *t) { free_trip(t); }
}; };
// Owning pointers to dive, dive_trip, dive_site and event objects. // Owning pointers to dive, dive_trip, dive_site and event objects.
using OwningDivePtr = std::unique_ptr<dive, DiveDeleter>;
using OwningTripPtr = std::unique_ptr<dive_trip, TripDeleter>; using OwningTripPtr = std::unique_ptr<dive_trip, TripDeleter>;
#endif #endif

View file

@ -657,10 +657,9 @@ static void uddf_gasswitch(const char *buffer, struct sample *sample, struct par
{ {
int idx = atoi(buffer); int idx = atoi(buffer);
int seconds = sample->time.seconds; int seconds = sample->time.seconds;
struct dive *dive = state->cur_dive;
struct divecomputer *dc = get_dc(state); struct divecomputer *dc = get_dc(state);
add_gas_switch_event(dive, dc, seconds, idx); add_gas_switch_event(state->cur_dive.get(), dc, seconds, idx);
} }
static int uddf_fill_sample(struct sample *sample, const char *name, char *buf, struct parser_state *state) static int uddf_fill_sample(struct sample *sample, const char *name, char *buf, struct parser_state *state)
@ -696,7 +695,7 @@ static void get_cylinderindex(const char *buffer, int16_t *i, struct parser_stat
{ {
*i = atoi(buffer); *i = atoi(buffer);
if (state->lastcylinderindex != *i) { if (state->lastcylinderindex != *i) {
add_gas_switch_event(state->cur_dive, get_dc(state), state->cur_sample->time.seconds, *i); add_gas_switch_event(state->cur_dive.get(), get_dc(state), state->cur_sample->time.seconds, *i);
state->lastcylinderindex = *i; state->lastcylinderindex = *i;
} }
} }
@ -1526,7 +1525,7 @@ static bool entry(const char *name, char *buf, struct parser_state *state)
return true; return true;
} }
if (state->cur_dive) { if (state->cur_dive) {
try_to_fill_dive(state->cur_dive, name, buf, state); try_to_fill_dive(state->cur_dive.get(), name, buf, state);
return true; return true;
} }
if (state->cur_trip) { if (state->cur_trip) {
@ -1863,7 +1862,7 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size, struct divelog *log)
state.cur_dc->surface_pressure.mbar = ((ptr[25] << 8) + ptr[24]) / 10; state.cur_dc->surface_pressure.mbar = ((ptr[25] << 8) + ptr[24]) / 10;
// Declare initial mix as first cylinder // Declare initial mix as first cylinder
cyl = get_or_create_cylinder(state.cur_dive, 0); cyl = get_or_create_cylinder(state.cur_dive.get(), 0);
cyl->gasmix.o2.permille = ptr[26] * 10; cyl->gasmix.o2.permille = ptr[26] * 10;
cyl->gasmix.he.permille = ptr[27] * 10; cyl->gasmix.he.permille = ptr[27] * 10;
@ -1974,7 +1973,7 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size, struct divelog *log)
found = false; found = false;
for (i = 0; i < state.cur_dive->cylinders.nr; ++i) { for (i = 0; i < state.cur_dive->cylinders.nr; ++i) {
const cylinder_t *cyl = get_cylinder(state.cur_dive, i); const cylinder_t *cyl = get_cylinder(state.cur_dive.get(), i);
if (cyl->gasmix.o2.permille == ptr[6] * 10 && cyl->gasmix.he.permille == ptr[7] * 10) { if (cyl->gasmix.o2.permille == ptr[6] * 10 && cyl->gasmix.he.permille == ptr[7] * 10) {
found = true; found = true;
break; break;
@ -2225,7 +2224,7 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size, struct divelog *log)
/* Measure GPS */ /* Measure GPS */
state.cur_location.lat.udeg = (int)((ptr[7] << 24) + (ptr[6] << 16) + (ptr[5] << 8) + (ptr[4] << 0)); state.cur_location.lat.udeg = (int)((ptr[7] << 24) + (ptr[6] << 16) + (ptr[5] << 8) + (ptr[4] << 0));
state.cur_location.lon.udeg = (int)((ptr[11] << 24) + (ptr[10] << 16) + (ptr[9] << 8) + (ptr[8] << 0)); state.cur_location.lon.udeg = (int)((ptr[11] << 24) + (ptr[10] << 16) + (ptr[9] << 8) + (ptr[8] << 0));
state.log->sites->create("DLF imported"s, state.cur_location)->add_dive(state.cur_dive); state.log->sites->create("DLF imported"s, state.cur_location)->add_dive(state.cur_dive.get());
break; break;
default: default:
break; break;

View file

@ -25,7 +25,6 @@ parser_state::parser_state()
parser_state::~parser_state() parser_state::~parser_state()
{ {
free_dive(cur_dive);
free_trip(cur_trip); free_trip(cur_trip);
} }
@ -264,7 +263,7 @@ void dive_start(struct parser_state *state)
{ {
if (state->cur_dive) if (state->cur_dive)
return; return;
state->cur_dive = alloc_dive(); state->cur_dive = std::make_unique<dive>();
reset_dc_info(&state->cur_dive->dc, state); reset_dc_info(&state->cur_dive->dc, state);
memset(&state->cur_tm, 0, sizeof(state->cur_tm)); memset(&state->cur_tm, 0, sizeof(state->cur_tm));
state->o2pressure_sensor = 1; state->o2pressure_sensor = 1;
@ -274,14 +273,12 @@ void dive_end(struct parser_state *state)
{ {
if (!state->cur_dive) if (!state->cur_dive)
return; return;
if (!is_dive(state)) { if (is_dive(state)) {
free_dive(state->cur_dive);
} else {
record_dive_to_table(state->cur_dive, state->log->dives.get());
if (state->cur_trip) if (state->cur_trip)
add_dive_to_trip(state->cur_dive, state->cur_trip); add_dive_to_trip(state->cur_dive.get(), state->cur_trip);
record_dive_to_table(state->cur_dive.release(), state->log->dives.get());
} }
state->cur_dive = NULL; state->cur_dive.reset();
state->cur_dc = NULL; state->cur_dc = NULL;
state->cur_location.lat.udeg = 0; state->cur_location.lat.udeg = 0;
state->cur_location.lon.udeg = 0; state->cur_location.lon.udeg = 0;
@ -369,8 +366,8 @@ void sample_start(struct parser_state *state)
sample->pressure[0].mbar = 0; sample->pressure[0].mbar = 0;
sample->pressure[1].mbar = 0; sample->pressure[1].mbar = 0;
} else { } else {
sample->sensor[0] = sanitize_sensor_id(state->cur_dive, !state->o2pressure_sensor); sample->sensor[0] = sanitize_sensor_id(state->cur_dive.get(), !state->o2pressure_sensor);
sample->sensor[1] = sanitize_sensor_id(state->cur_dive, state->o2pressure_sensor); sample->sensor[1] = sanitize_sensor_id(state->cur_dive.get(), state->o2pressure_sensor);
} }
state->cur_sample = sample; state->cur_sample = sample;
state->next_o2_sensor = 0; state->next_o2_sensor = 0;
@ -396,7 +393,7 @@ void divecomputer_start(struct parser_state *state)
/* Did we already fill that in? */ /* Did we already fill that in? */
if (dc->samples || dc->model || dc->when) { if (dc->samples || dc->model || dc->when) {
struct divecomputer *newdc = (divecomputer *)calloc(1, sizeof(*newdc)); struct divecomputer *newdc = new divecomputer;
if (newdc) { if (newdc) {
dc->next = newdc; dc->next = newdc;
dc = newdc; dc = newdc;

View file

@ -54,7 +54,7 @@ struct parser_state {
enum import_source import_source = UNKNOWN; enum import_source import_source = UNKNOWN;
struct divecomputer *cur_dc = nullptr; /* non-owning */ struct divecomputer *cur_dc = nullptr; /* non-owning */
struct dive *cur_dive = nullptr; /* owning */ std::unique_ptr<dive> cur_dive; /* owning */
std::unique_ptr<dive_site> cur_dive_site; /* owning */ std::unique_ptr<dive_site> cur_dive_site; /* owning */
location_t cur_location; location_t cur_location;
struct dive_trip *cur_trip = nullptr; /* owning */ struct dive_trip *cur_trip = nullptr; /* owning */

View file

@ -185,9 +185,9 @@ static void uemis_get_weight(std::string_view buffer, weightsystem_t &weight, in
weight.description = translate("gettextFromC", "unknown"); weight.description = translate("gettextFromC", "unknown");
} }
static struct dive *uemis_start_dive(uint32_t deviceid) static std::unique_ptr<dive> uemis_start_dive(uint32_t deviceid)
{ {
struct dive *dive = alloc_dive(); auto dive = std::make_unique<struct dive>();
dive->dc.model = strdup("Uemis Zurich"); dive->dc.model = strdup("Uemis Zurich");
dive->dc.deviceid = deviceid; dive->dc.deviceid = deviceid;
return dive; return dive;
@ -788,7 +788,7 @@ static bool uemis_delete_dive(device_data_t *devdata, uint32_t diveid)
} }
if (dive) { if (dive) {
devdata->log->dives->dives[--devdata->log->dives->nr] = NULL; devdata->log->dives->dives[--devdata->log->dives->nr] = NULL;
free_dive(dive); delete dive;
return true; return true;
} }
@ -810,9 +810,10 @@ static bool process_raw_buffer(device_data_t *devdata, uint32_t deviceid, std::s
{ {
using namespace std::string_literals; using namespace std::string_literals;
bool done = false; bool done = false;
bool is_log = false, is_dive = false; bool is_log = false;
std::vector<std::string_view> sections; std::vector<std::string_view> sections;
struct dive *dive = NULL; std::unique_ptr<dive> owned_dive; // in log mode
struct dive *non_owned_dive = nullptr; // in dive (non-log) mode
int dive_no = 0; int dive_no = 0;
#if UEMIS_DEBUG & 8 #if UEMIS_DEBUG & 8
@ -831,7 +832,7 @@ static bool process_raw_buffer(device_data_t *devdata, uint32_t deviceid, std::s
return false; return false;
} else if (tp == "dive") { } else if (tp == "dive") {
/* this is dive detail */ /* this is dive detail */
is_dive = true; is_log = false;
tp = next_token(bp); tp = next_token(bp);
if (tp != "1.0") if (tp != "1.0")
return false; return false;
@ -840,7 +841,7 @@ static bool process_raw_buffer(device_data_t *devdata, uint32_t deviceid, std::s
return false; return false;
} }
if (is_log) { if (is_log) {
dive = uemis_start_dive(deviceid); owned_dive = uemis_start_dive(deviceid);
} else { } else {
/* remember, we don't know if this is the right entry, /* remember, we don't know if this is the right entry,
* so first test if this is even a valid entry */ * so first test if this is even a valid entry */
@ -897,36 +898,18 @@ static bool process_raw_buffer(device_data_t *devdata, uint32_t deviceid, std::s
std::string(type).c_str(), std::string(type).c_str(),
std::string(val).c_str()); std::string(val).c_str());
#endif #endif
if (is_log && tag == "object_id") { if (is_log) {
// Is log
if (tag == "object_id") {
from_chars(val, max_divenr); from_chars(val, max_divenr);
dive->dc.diveid = max_divenr; owned_dive->dc.diveid = max_divenr;
#if UEMIS_DEBUG % 2 #if UEMIS_DEBUG % 2
report_info("Adding new dive from log with object_id %d.\n", max_divenr); report_info("Adding new dive from log with object_id %d.\n", max_divenr);
#endif #endif
} else if (is_dive && tag == "logfilenr") {
/* this one tells us which dive we are adding data to */
int diveid = 0;
from_chars(val, diveid);
dive = get_dive_by_uemis_diveid(devdata, diveid);
if (dive_no != 0)
dive->number = dive_no;
if (for_dive)
*for_dive = diveid;
} else if (!is_log && dive && tag == "divespot_id") {
int divespot_id;
if (from_chars(val, divespot_id).ec != std::errc::invalid_argument) {
struct dive_site *ds = devdata->log->sites->create("from Uemis"s);
unregister_dive_from_dive_site(dive);
ds->add_dive(dive);
uemis_obj.mark_divelocation(dive->dc.diveid, divespot_id, ds);
} }
#if UEMIS_DEBUG & 2 parse_tag(owned_dive.get(), tag, val);
report_info("Created divesite %d for diveid : %d\n", dive->dive_site->uuid, dive->dc.diveid);
#endif if (tag == "file_content")
} else if (dive) {
parse_tag(dive, tag, val);
}
if (is_log && tag == "file_content")
done = true; done = true;
/* done with one dive (got the file_content tag), but there could be more: /* done with one dive (got the file_content tag), but there could be more:
* a '{' indicates the end of the record - but we need to see another "{{" * a '{' indicates the end of the record - but we need to see another "{{"
@ -936,19 +919,43 @@ static bool process_raw_buffer(device_data_t *devdata, uint32_t deviceid, std::s
bp = bp.substr(1); bp = bp.substr(1);
if (bp[0] != '{' && bp.find("{{") != std::string::npos) { if (bp[0] != '{' && bp.find("{{") != std::string::npos) {
done = false; done = false;
record_dive_to_table(dive, devdata->log->dives.get()); record_dive_to_table(owned_dive.release(), devdata->log->dives.get());
dive = uemis_start_dive(deviceid); owned_dive = uemis_start_dive(deviceid);
}
}
} else {
// Is dive
if (tag == "logfilenr") {
/* this one tells us which dive we are adding data to */
int diveid = 0;
from_chars(val, diveid);
non_owned_dive = get_dive_by_uemis_diveid(devdata, diveid);
if (dive_no != 0)
non_owned_dive->number = dive_no;
if (for_dive)
*for_dive = diveid;
} else if (non_owned_dive && tag == "divespot_id") {
int divespot_id;
if (from_chars(val, divespot_id).ec != std::errc::invalid_argument) {
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);
}
#if UEMIS_DEBUG & 2
report_info("Created divesite %d for diveid : %d\n", non_owned_dive->dive_site->uuid, non_owned_dive->dc.diveid);
#endif
} else if (non_owned_dive) {
parse_tag(non_owned_dive, tag, val);
} }
} }
} }
if (is_log) { if (is_log) {
if (dive->dc.diveid) { if (owned_dive->dc.diveid)
record_dive_to_table(dive, devdata->log->dives.get()); record_dive_to_table(owned_dive.release(), devdata->log->dives.get());
} else { /* partial dive */ else /* partial dive */
free_dive(dive);
return false; return false;
} }
}
return true; return true;
} }

View file

@ -537,7 +537,7 @@ void PlannerDetails::setPlanNotes(QString plan)
} }
PlannerWidgets::PlannerWidgets() : PlannerWidgets::PlannerWidgets() :
planned_dive(alloc_dive()), planned_dive(std::make_unique<dive>()),
dcNr(0), dcNr(0),
plannerWidget(*planned_dive, dcNr, this), plannerWidget(*planned_dive, dcNr, this),
plannerSettingsWidget(this) plannerSettingsWidget(this)

View file

@ -3,8 +3,8 @@
#define DIVEPLANNER_H #define DIVEPLANNER_H
#include "core/divemode.h" #include "core/divemode.h"
#include "core/owning_ptrs.h"
#include <memory>
#include <QAbstractTableModel> #include <QAbstractTableModel>
#include <QAbstractButton> #include <QAbstractButton>
#include <QDateTime> #include <QDateTime>
@ -91,7 +91,7 @@ public
slots: slots:
void printDecoPlan(); void printDecoPlan();
private: private:
OwningDivePtr planned_dive; std::unique_ptr<dive> planned_dive;
int dcNr; int dcNr;
public: public:
DivePlannerWidget plannerWidget; DivePlannerWidget plannerWidget;

View file

@ -209,7 +209,6 @@ MainWindow::MainWindow() :
#ifdef NO_USERMANUAL #ifdef NO_USERMANUAL
ui.menuHelp->removeAction(ui.actionUserManual); ui.menuHelp->removeAction(ui.actionUserManual);
#endif #endif
memset(&copyPasteDive, 0, sizeof(copyPasteDive));
memset(&what, 0, sizeof(what)); memset(&what, 0, sizeof(what));
updateManager = new UpdateManager(this); updateManager = new UpdateManager(this);
@ -703,7 +702,7 @@ void MainWindow::on_actionAddDive_triggered()
// create a dive an hour from now with a default depth (15m/45ft) and duration (40 minutes) // create a dive an hour from now with a default depth (15m/45ft) and duration (40 minutes)
// as a starting point for the user to edit // as a starting point for the user to edit
struct dive d = { 0 }; struct dive d;
d.id = dive_getUniqID(); d.id = dive_getUniqID();
d.when = QDateTime::currentMSecsSinceEpoch() / 1000L + gettimezoneoffset() + 3600; d.when = QDateTime::currentMSecsSinceEpoch() / 1000L + gettimezoneoffset() + 3600;
d.dc.duration.seconds = 40 * 60; d.dc.duration.seconds = 40 * 60;

View file

@ -324,7 +324,7 @@ void ProfileWidget::unsetProfTissues()
void ProfileWidget::editDive() void ProfileWidget::editDive()
{ {
editedDive.reset(alloc_dive()); editedDive = std::make_unique<dive>();
copy_dive(d, editedDive.get()); // Work on a copy of the dive copy_dive(d, editedDive.get()); // Work on a copy of the dive
DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::EDIT); DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::EDIT);
DivePlannerPointsModel::instance()->loadFromDive(editedDive.get(), dc); DivePlannerPointsModel::instance()->loadFromDive(editedDive.get(), dc);

View file

@ -48,7 +48,7 @@ private:
void editDive(); void editDive();
void exitEditMode(); void exitEditMode();
void rotateDC(int dir); void rotateDC(int dir);
OwningDivePtr editedDive; std::unique_ptr<dive> editedDive;
bool placingCommand; bool placingCommand;
}; };

View file

@ -1191,7 +1191,7 @@ void QMLManager::commitChanges(QString diveId, QString number, QString date, QSt
report_info("state :'%s'", qPrintable(state)); report_info("state :'%s'", qPrintable(state));
} }
OwningDivePtr d_ptr(alloc_dive()); // Automatically delete dive if we exit early! auto d_ptr = std::make_unique<dive>(); // Automatically delete dive if we exit early!
dive *d = d_ptr.get(); dive *d = d_ptr.get();
copy_dive(orig, d); copy_dive(orig, d);
@ -1728,7 +1728,7 @@ int QMLManager::addDive()
// TODO: Duplicate code with desktop-widgets/mainwindow.cpp // TODO: Duplicate code with desktop-widgets/mainwindow.cpp
// create a dive an hour from now with a default depth (15m/45ft) and duration (40 minutes) // create a dive an hour from now with a default depth (15m/45ft) and duration (40 minutes)
// as a starting point for the user to edit // as a starting point for the user to edit
struct dive d = { 0 }; struct dive d;
int diveId = d.id = dive_getUniqID(); int diveId = d.id = dive_getUniqID();
d.when = QDateTime::currentMSecsSinceEpoch() / 1000L + gettimezoneoffset() + 3600; d.when = QDateTime::currentMSecsSinceEpoch() / 1000L + gettimezoneoffset() + 3600;
d.dc.duration.seconds = 40 * 60; d.dc.duration.seconds = 40 * 60;

View file

@ -1185,8 +1185,8 @@ void DivePlannerPointsModel::computeVariations(struct diveplan *original_plan, c
if (!original_plan) if (!original_plan)
return; return;
struct dive *dive = alloc_dive(); auto dive = std::make_unique<struct dive>();
copy_dive(d, dive); copy_dive(d, dive.get());
struct decostop original[60], deeper[60], shallower[60], shorter[60], longer[60]; struct decostop original[60], deeper[60], shallower[60], shorter[60], longer[60];
deco_state_cache cache, save; deco_state_cache cache, save;
struct diveplan plan_copy; struct diveplan plan_copy;
@ -1214,7 +1214,7 @@ void DivePlannerPointsModel::computeVariations(struct diveplan *original_plan, c
goto finish; goto finish;
if (my_instance != instanceCounter) if (my_instance != instanceCounter)
goto finish; goto finish;
plan(&ds, &plan_copy, dive, dcNr, 1, original, cache, true, false); plan(&ds, &plan_copy, dive.get(), dcNr, 1, original, cache, true, false);
free_dps(&plan_copy); free_dps(&plan_copy);
save.restore(&ds, false); save.restore(&ds, false);
@ -1223,7 +1223,7 @@ void DivePlannerPointsModel::computeVariations(struct diveplan *original_plan, c
last_segment->next->depth.mm += delta_depth.mm; last_segment->next->depth.mm += delta_depth.mm;
if (my_instance != instanceCounter) if (my_instance != instanceCounter)
goto finish; goto finish;
plan(&ds, &plan_copy, dive, dcNr, 1, deeper, cache, true, false); plan(&ds, &plan_copy, dive.get(), dcNr, 1, deeper, cache, true, false);
free_dps(&plan_copy); free_dps(&plan_copy);
save.restore(&ds, false); save.restore(&ds, false);
@ -1232,7 +1232,7 @@ void DivePlannerPointsModel::computeVariations(struct diveplan *original_plan, c
last_segment->next->depth.mm -= delta_depth.mm; last_segment->next->depth.mm -= delta_depth.mm;
if (my_instance != instanceCounter) if (my_instance != instanceCounter)
goto finish; goto finish;
plan(&ds, &plan_copy, dive, dcNr, 1, shallower, cache, true, false); plan(&ds, &plan_copy, dive.get(), dcNr, 1, shallower, cache, true, false);
free_dps(&plan_copy); free_dps(&plan_copy);
save.restore(&ds, false); save.restore(&ds, false);
@ -1240,7 +1240,7 @@ void DivePlannerPointsModel::computeVariations(struct diveplan *original_plan, c
last_segment->next->time += delta_time.seconds; last_segment->next->time += delta_time.seconds;
if (my_instance != instanceCounter) if (my_instance != instanceCounter)
goto finish; goto finish;
plan(&ds, &plan_copy, dive, dcNr, 1, longer, cache, true, false); plan(&ds, &plan_copy, dive.get(), dcNr, 1, longer, cache, true, false);
free_dps(&plan_copy); free_dps(&plan_copy);
save.restore(&ds, false); save.restore(&ds, false);
@ -1248,7 +1248,7 @@ void DivePlannerPointsModel::computeVariations(struct diveplan *original_plan, c
last_segment->next->time -= delta_time.seconds; last_segment->next->time -= delta_time.seconds;
if (my_instance != instanceCounter) if (my_instance != instanceCounter)
goto finish; goto finish;
plan(&ds, &plan_copy, dive, dcNr, 1, shorter, cache, true, false); plan(&ds, &plan_copy, dive.get(), dcNr, 1, shorter, cache, true, false);
free_dps(&plan_copy); free_dps(&plan_copy);
save.restore(&ds, false); save.restore(&ds, false);
@ -1265,7 +1265,6 @@ void DivePlannerPointsModel::computeVariations(struct diveplan *original_plan, c
finish: finish:
free_dps(original_plan); free_dps(original_plan);
free(original_plan); free(original_plan);
free_dive(dive);
} }
void DivePlannerPointsModel::computeVariationsDone(QString variations) void DivePlannerPointsModel::computeVariationsDone(QString variations)

View file

@ -926,7 +926,7 @@ void smartrak_import(const char *file, struct divelog *log)
device_data_t devdata; device_data_t devdata;
dc_family_t dc_fam = DC_FAMILY_NULL; dc_family_t dc_fam = DC_FAMILY_NULL;
unsigned char *prf_buffer, *hdr_buffer; unsigned char *prf_buffer, *hdr_buffer;
struct dive *smtkdive = alloc_dive(); auto smtkdive = std::make_unique<dive>();
struct tm tm_date; struct tm tm_date;
size_t hdr_length, prf_length; size_t hdr_length, prf_length;
dc_status_t rc = DC_STATUS_SUCCESS; dc_status_t rc = DC_STATUS_SUCCESS;
@ -956,7 +956,7 @@ void smartrak_import(const char *file, struct divelog *log)
if (rc != DC_STATUS_SUCCESS) { if (rc != DC_STATUS_SUCCESS) {
report_error("[Error][smartrak_import]\t- %s - for dive %d", errmsg(rc), smtkdive->number); report_error("[Error][smartrak_import]\t- %s - for dive %d", errmsg(rc), smtkdive->number);
} else { } else {
rc = libdc_buffer_parser(smtkdive, &devdata, compl_buffer.data(), hdr_length + prf_length); rc = libdc_buffer_parser(smtkdive.get(), &devdata, compl_buffer.data(), hdr_length + prf_length);
if (rc != DC_STATUS_SUCCESS) if (rc != DC_STATUS_SUCCESS)
report_error("[Error][libdc]\t\t- %s - for dive %d", errmsg(rc), smtkdive->number); report_error("[Error][libdc]\t\t- %s - for dive %d", errmsg(rc), smtkdive->number);
} }
@ -985,7 +985,7 @@ void smartrak_import(const char *file, struct divelog *log)
int tankidxcol = coln(TANKIDX); int tankidxcol = coln(TANKIDX);
for (i = 0; i < tanks; i++) { for (i = 0; i < tanks; i++) {
cylinder_t *tmptank = get_or_create_cylinder(smtkdive, i); cylinder_t *tmptank = get_or_create_cylinder(smtkdive.get(), i);
if (!tmptank) if (!tmptank)
break; break;
if (tmptank->start.mbar == 0) if (tmptank->start.mbar == 0)
@ -1008,7 +1008,7 @@ void smartrak_import(const char *file, struct divelog *log)
smtk_build_tank_info(mdb_clon, tmptank, (char *)col[i + tankidxcol]->bind_ptr); smtk_build_tank_info(mdb_clon, tmptank, (char *)col[i + tankidxcol]->bind_ptr);
} }
/* Check for duplicated cylinders and clean them */ /* Check for duplicated cylinders and clean them */
smtk_clean_cylinders(smtkdive); smtk_clean_cylinders(smtkdive.get());
/* Date issues with libdc parser - Take date time from mdb */ /* Date issues with libdc parser - Take date time from mdb */
smtk_date_to_tm((char *)col[coln(_DATE)]->bind_ptr, &tm_date); smtk_date_to_tm((char *)col[coln(_DATE)]->bind_ptr, &tm_date);
@ -1031,17 +1031,17 @@ void smartrak_import(const char *file, struct divelog *log)
smtkdive->suit = strdup(get(suit_list, atoi((char *)col[coln(SUITIDX)]->bind_ptr) - 1).c_str()); smtkdive->suit = strdup(get(suit_list, atoi((char *)col[coln(SUITIDX)]->bind_ptr) - 1).c_str());
smtk_build_location(mdb_clon, (char *)col[coln(SITEIDX)]->bind_ptr, &smtkdive->dive_site, log); smtk_build_location(mdb_clon, (char *)col[coln(SITEIDX)]->bind_ptr, &smtkdive->dive_site, log);
smtkdive->buddy = strdup(smtk_locate_buddy(mdb_clon, (char *)col[0]->bind_ptr, buddy_list).c_str()); smtkdive->buddy = strdup(smtk_locate_buddy(mdb_clon, (char *)col[0]->bind_ptr, buddy_list).c_str());
smtk_parse_relations(mdb_clon, smtkdive, (char *)col[0]->bind_ptr, "Type", "TypeRelation", type_list, true); smtk_parse_relations(mdb_clon, smtkdive.get(), (char *)col[0]->bind_ptr, "Type", "TypeRelation", type_list, true);
smtk_parse_relations(mdb_clon, smtkdive, (char *)col[0]->bind_ptr, "Activity", "ActivityRelation", activity_list, false); smtk_parse_relations(mdb_clon, smtkdive.get(), (char *)col[0]->bind_ptr, "Activity", "ActivityRelation", activity_list, false);
smtk_parse_relations(mdb_clon, smtkdive, (char *)col[0]->bind_ptr, "Gear", "GearRelation", gear_list, false); smtk_parse_relations(mdb_clon, smtkdive.get(), (char *)col[0]->bind_ptr, "Gear", "GearRelation", gear_list, false);
smtk_parse_relations(mdb_clon, smtkdive, (char *)col[0]->bind_ptr, "Fish", "FishRelation", fish_list, false); smtk_parse_relations(mdb_clon, smtkdive.get(), (char *)col[0]->bind_ptr, "Fish", "FishRelation", fish_list, false);
smtk_parse_other(smtkdive, weather_list, "Weather", (char *)col[coln(WEATHERIDX)]->bind_ptr, false); smtk_parse_other(smtkdive.get(), weather_list, "Weather", (char *)col[coln(WEATHERIDX)]->bind_ptr, false);
smtk_parse_other(smtkdive, underwater_list, "Underwater", (char *)col[coln(UNDERWATERIDX)]->bind_ptr, false); smtk_parse_other(smtkdive.get(), underwater_list, "Underwater", (char *)col[coln(UNDERWATERIDX)]->bind_ptr, false);
smtk_parse_other(smtkdive, surface_list, "Surface", (char *)col[coln(SURFACEIDX)]->bind_ptr, false); smtk_parse_other(smtkdive.get(), surface_list, "Surface", (char *)col[coln(SURFACEIDX)]->bind_ptr, false);
smtk_parse_bookmarks(mdb_clon, smtkdive, (char *)col[0]->bind_ptr); smtk_parse_bookmarks(mdb_clon, smtkdive.get(), (char *)col[0]->bind_ptr);
concat(&smtkdive->notes, "\n", std::string((char *)col[coln(REMARKS)]->bind_ptr)); concat(&smtkdive->notes, "\n", std::string((char *)col[coln(REMARKS)]->bind_ptr));
record_dive_to_table(smtkdive, log->dives.get()); record_dive_to_table(smtkdive.release(), log->dives.get());
} }
mdb_free_catalog(mdb_clon); mdb_free_catalog(mdb_clon);
mdb->catalog = NULL; mdb->catalog = NULL;

View file

@ -9,14 +9,14 @@ void TestformatDiveGasString::init()
void TestformatDiveGasString::test_empty() void TestformatDiveGasString::test_empty()
{ {
struct dive dive = {0}; struct dive dive;
QCOMPARE(formatDiveGasString(&dive), "air"); QCOMPARE(formatDiveGasString(&dive), "air");
} }
void TestformatDiveGasString::test_air() void TestformatDiveGasString::test_air()
{ {
struct dive dive = {0}; struct dive dive;
cylinder_t *cylinder = get_or_create_cylinder(&dive, 0); cylinder_t *cylinder = get_or_create_cylinder(&dive, 0);
cylinder->start.mbar = 230000; cylinder->start.mbar = 230000;
@ -25,8 +25,9 @@ void TestformatDiveGasString::test_air()
QCOMPARE(formatDiveGasString(&dive), "air"); QCOMPARE(formatDiveGasString(&dive), "air");
} }
void TestformatDiveGasString::test_nitrox() { void TestformatDiveGasString::test_nitrox()
struct dive dive = {0}; {
struct dive dive;
cylinder_t *cylinder = get_or_create_cylinder(&dive, 0); cylinder_t *cylinder = get_or_create_cylinder(&dive, 0);
cylinder->gasmix.o2.permille = 320; cylinder->gasmix.o2.permille = 320;
@ -36,8 +37,9 @@ void TestformatDiveGasString::test_nitrox() {
QCOMPARE(formatDiveGasString(&dive), "32%"); QCOMPARE(formatDiveGasString(&dive), "32%");
} }
void TestformatDiveGasString::test_nitrox_not_use() { void TestformatDiveGasString::test_nitrox_not_use()
struct dive dive = {0}; {
struct dive dive;
cylinder_t *cylinder = get_or_create_cylinder(&dive, 0); cylinder_t *cylinder = get_or_create_cylinder(&dive, 0);
cylinder->gasmix.o2.permille = 320; cylinder->gasmix.o2.permille = 320;
@ -54,8 +56,9 @@ void TestformatDiveGasString::test_nitrox_not_use() {
QCOMPARE(formatDiveGasString(&dive), "32%"); QCOMPARE(formatDiveGasString(&dive), "32%");
} }
void TestformatDiveGasString::test_nitrox_deco() { void TestformatDiveGasString::test_nitrox_deco()
struct dive dive = {0}; {
struct dive dive;
cylinder_t *cylinder = get_or_create_cylinder(&dive, 0); cylinder_t *cylinder = get_or_create_cylinder(&dive, 0);
cylinder->gasmix.o2.permille = 320; cylinder->gasmix.o2.permille = 320;
@ -71,8 +74,9 @@ void TestformatDiveGasString::test_nitrox_deco() {
QCOMPARE(formatDiveGasString(&dive), "32…100%"); QCOMPARE(formatDiveGasString(&dive), "32…100%");
} }
void TestformatDiveGasString::test_reverse_nitrox_deco() { void TestformatDiveGasString::test_reverse_nitrox_deco()
struct dive dive = {0}; {
struct dive dive;
cylinder_t *cylinder = get_or_create_cylinder(&dive, 0); cylinder_t *cylinder = get_or_create_cylinder(&dive, 0);
cylinder->gasmix.o2.permille = 1000; cylinder->gasmix.o2.permille = 1000;
@ -88,8 +92,9 @@ void TestformatDiveGasString::test_reverse_nitrox_deco() {
QCOMPARE(formatDiveGasString(&dive), "27…100%"); QCOMPARE(formatDiveGasString(&dive), "27…100%");
} }
void TestformatDiveGasString::test_trimix() { void TestformatDiveGasString::test_trimix()
struct dive dive = {0}; {
struct dive dive;
cylinder_t *cylinder = get_or_create_cylinder(&dive, 0); cylinder_t *cylinder = get_or_create_cylinder(&dive, 0);
cylinder->gasmix.o2.permille = 210; cylinder->gasmix.o2.permille = 210;
@ -100,8 +105,9 @@ void TestformatDiveGasString::test_trimix() {
QCOMPARE(formatDiveGasString(&dive), "21/35"); QCOMPARE(formatDiveGasString(&dive), "21/35");
} }
void TestformatDiveGasString::test_trimix_deco() { void TestformatDiveGasString::test_trimix_deco()
struct dive dive = {0}; {
struct dive dive;
cylinder_t *cylinder = get_or_create_cylinder(&dive, 0); cylinder_t *cylinder = get_or_create_cylinder(&dive, 0);
cylinder->gasmix.o2.permille = 210; cylinder->gasmix.o2.permille = 210;
@ -125,8 +131,9 @@ void TestformatDiveGasString::test_trimix_deco() {
QCOMPARE(formatDiveGasString(&dive), "21/35…100%"); QCOMPARE(formatDiveGasString(&dive), "21/35…100%");
} }
void TestformatDiveGasString::test_reverse_trimix_deco() { void TestformatDiveGasString::test_reverse_trimix_deco()
struct dive dive = {0}; {
struct dive dive;
cylinder_t *cylinder = get_or_create_cylinder(&dive, 0); cylinder_t *cylinder = get_or_create_cylinder(&dive, 0);
cylinder->gasmix.o2.permille = 1000; cylinder->gasmix.o2.permille = 1000;
@ -150,8 +157,9 @@ void TestformatDiveGasString::test_reverse_trimix_deco() {
QCOMPARE(formatDiveGasString(&dive), "21/35…100%"); QCOMPARE(formatDiveGasString(&dive), "21/35…100%");
} }
void TestformatDiveGasString::test_trimix_and_nitrox_same_o2() { void TestformatDiveGasString::test_trimix_and_nitrox_same_o2()
struct dive dive = {0}; {
struct dive dive;
cylinder_t *cylinder = get_or_create_cylinder(&dive, 0); cylinder_t *cylinder = get_or_create_cylinder(&dive, 0);
cylinder->gasmix.o2.permille = 250; cylinder->gasmix.o2.permille = 250;
@ -169,8 +177,9 @@ void TestformatDiveGasString::test_trimix_and_nitrox_same_o2() {
QCOMPARE(formatDiveGasString(&dive), "25/25"); QCOMPARE(formatDiveGasString(&dive), "25/25");
} }
void TestformatDiveGasString::test_trimix_and_nitrox_lower_o2() { void TestformatDiveGasString::test_trimix_and_nitrox_lower_o2()
struct dive dive = {0}; {
struct dive dive;
cylinder_t *cylinder = get_or_create_cylinder(&dive, 0); cylinder_t *cylinder = get_or_create_cylinder(&dive, 0);
cylinder->gasmix.o2.permille = 220; cylinder->gasmix.o2.permille = 220;
@ -188,8 +197,9 @@ void TestformatDiveGasString::test_trimix_and_nitrox_lower_o2() {
QCOMPARE(formatDiveGasString(&dive), "25/25"); QCOMPARE(formatDiveGasString(&dive), "25/25");
} }
void TestformatDiveGasString::test_ccr() { void TestformatDiveGasString::test_ccr()
struct dive dive = {0}; {
struct dive dive;
cylinder_t *cylinder = get_or_create_cylinder(&dive, 0); cylinder_t *cylinder = get_or_create_cylinder(&dive, 0);
cylinder->gasmix.o2.permille = 1000; cylinder->gasmix.o2.permille = 1000;
@ -208,8 +218,9 @@ void TestformatDiveGasString::test_ccr() {
QCOMPARE(formatDiveGasString(&dive), "21/35"); QCOMPARE(formatDiveGasString(&dive), "21/35");
} }
void TestformatDiveGasString::test_ccr_bailout() { void TestformatDiveGasString::test_ccr_bailout()
struct dive dive = {0}; {
struct dive dive;
cylinder_t *cylinder = get_or_create_cylinder(&dive, 0); cylinder_t *cylinder = get_or_create_cylinder(&dive, 0);
cylinder->gasmix.o2.permille = 1000; cylinder->gasmix.o2.permille = 1000;

View file

@ -12,7 +12,7 @@
#define DEBUG 1 #define DEBUG 1
// testing the dive plan algorithm // testing the dive plan algorithm
static struct dive dive = { 0 }; static struct dive dive;
static struct decostop stoptable[60]; static struct decostop stoptable[60];
static struct deco_state test_deco_state; static struct deco_state test_deco_state;
extern bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, int dcNr, int timestep, struct decostop *decostoptable, deco_state_cache &cache, bool is_planner, bool show_disclaimer); extern bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, int dcNr, int timestep, struct decostop *decostoptable, deco_state_cache &cache, bool is_planner, bool show_disclaimer);