divelog: turn owning-pointers into unique_ptr<>s

Since everything is C++ now, we can use unique_ptr<>s. This makes
the code significantly shorter, because we can now use the default
move constructor and assignment operators.

This has a semantic change when std::move()-ing the divelog:
now not the contents of the tables are moved, but the pointers.
That is, the moved-from object now has no more tables and
must not be used anymore. This made it necessary to replace
std::move()s by std::swap()s. In that regard, the old code was
in principle broken: it used moved-from objects, which may work
but usually doesn't.

This commit adds a myriad of .get() function calls where the code
expects a C-style pointer. The plan is to remove virtually all of
them, when we move free-standing functions into the class it acts
on. Or, replace C-style pointers by references where we don't support
NULL.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-05-13 19:34:43 +02:00 committed by bstoeger
parent 6e352d5281
commit d242198c99
22 changed files with 113 additions and 138 deletions

View file

@ -825,7 +825,7 @@ int try_to_open_cochran(const char *, std::string &mem, struct divelog *log)
break;
cochran_parse_dive(decode, mod, (unsigned char *)mem.data() + dive1,
dive2 - dive1, log->dives);
dive2 - dive1, log->dives.get());
}
return 1; // no further processing needed

View file

@ -700,7 +700,7 @@ int datatrak_import(std::string &mem, std::string &wl_mem, struct divelog *log)
runner = mem.data();
JUMP(runner, 12);
// Secuential parsing. Abort if received NULL from dt_dive_parser.
// Sequential parsing. Abort if received NULL from dt_dive_parser.
while ((i < numdives) && (runner < maxbuf)) {
struct dive *ptdive = alloc_dive();
@ -713,12 +713,12 @@ int datatrak_import(std::string &mem, std::string &wl_mem, struct divelog *log)
rc = 1;
goto out;
} else {
record_dive_to_table(ptdive, log->dives);
record_dive_to_table(ptdive, log->dives.get());
}
i++;
}
out:
sort_dive_table(log->dives);
sort_dive_table(log->dives.get());
return rc;
bail:
return 1;

View file

@ -140,7 +140,7 @@ int is_default_dive_computer_device(const char *name)
const char *get_dc_nickname(const struct divecomputer *dc)
{
const device *existNode = get_device_for_dc(divelog.devices, dc);
const device *existNode = get_device_for_dc(divelog.devices.get(), dc);
if (existNode && !existNode->nickName.empty())
return existNode->nickName.c_str();

View file

@ -758,7 +758,7 @@ struct dive *unregister_dive(int idx)
/* When removing a dive from the global dive table,
* we also have to unregister its fulltext cache. */
fulltext_unregister(dive);
remove_from_dive_table(divelog.dives, idx);
remove_from_dive_table(divelog.dives.get(), idx);
if (dive->selected)
amount_selected--;
dive->selected = false;
@ -767,11 +767,11 @@ struct dive *unregister_dive(int idx)
void process_loaded_dives()
{
sort_dive_table(divelog.dives);
sort_trip_table(divelog.trips);
sort_dive_table(divelog.dives.get());
sort_trip_table(divelog.trips.get());
/* Autogroup dives if desired by user. */
autogroup_dives(divelog.dives, divelog.trips);
autogroup_dives(divelog.dives.get(), divelog.trips.get());
fulltext_populate();
@ -982,12 +982,12 @@ void add_imported_dives(struct divelog *import_log, int flags)
/* Add new dives */
for (i = 0; i < dives_to_add.nr; i++)
insert_dive(divelog.dives, dives_to_add.dives[i]);
insert_dive(divelog.dives.get(), dives_to_add.dives[i]);
dives_to_add.nr = 0;
/* Add new trips */
for (i = 0; i < trips_to_add.nr; i++)
insert_trip(trips_to_add.trips[i], divelog.trips);
insert_trip(trips_to_add.trips[i], divelog.trips.get());
trips_to_add.nr = 0;
/* Add new dive sites */
@ -997,7 +997,7 @@ void add_imported_dives(struct divelog *import_log, int flags)
/* Add new devices */
for (i = 0; i < nr_devices(devices_to_add); i++) {
const struct device *dev = get_device(devices_to_add, i);
add_to_device_table(divelog.devices, dev);
add_to_device_table(divelog.devices.get(), dev);
}
/* We might have deleted the old selected dive.
@ -1113,20 +1113,20 @@ void process_imported_dives(struct divelog *import_log, int flags,
return;
/* Add only the devices that we don't know about yet. */
for (i = 0; i < nr_devices(import_log->devices); i++) {
const struct device *dev = get_device(import_log->devices, i);
if (!device_exists(divelog.devices, dev))
for (i = 0; i < nr_devices(import_log->devices.get()); i++) {
const struct device *dev = get_device(import_log->devices.get(), i);
if (!device_exists(divelog.devices.get(), dev))
add_to_device_table(devices_to_add, dev);
}
/* Sort the table of dives to be imported and combine mergable dives */
sort_dive_table(import_log->dives);
merge_imported_dives(import_log->dives);
sort_dive_table(import_log->dives.get());
merge_imported_dives(import_log->dives.get());
/* Autogroup tripless dives if desired by user. But don't autogroup
* if tripless dives should be added to a new trip. */
if (!(flags & IMPORT_ADD_TO_NEW_TRIP))
autogroup_dives(import_log->dives, import_log->trips);
autogroup_dives(import_log->dives.get(), import_log->trips.get());
/* If dive sites already exist, use the existing versions. */
for (auto &new_ds: *import_log->sites) {
@ -1164,7 +1164,7 @@ void process_imported_dives(struct divelog *import_log, int flags,
for (i = 0; i < import_log->trips->nr; i++) {
trip_import = import_log->trips->trips[i];
if ((flags & IMPORT_MERGE_ALL_TRIPS) || trip_import->autogen) {
if (try_to_merge_trip(trip_import, import_log->dives, flags & IMPORT_PREFER_IMPORTED, dives_to_add, dives_to_remove,
if (try_to_merge_trip(trip_import, import_log->dives.get(), flags & IMPORT_PREFER_IMPORTED, dives_to_add, dives_to_remove,
&sequence_changed, &start_renumbering_at))
continue;
}
@ -1178,7 +1178,7 @@ void process_imported_dives(struct divelog *import_log, int flags,
insert_dive(dives_to_add, d);
sequence_changed |= !dive_is_after_last(d);
remove_dive(d, import_log->dives);
remove_dive(d, import_log->dives.get());
}
/* Then, add trip to list of trips to add */
@ -1205,7 +1205,7 @@ void process_imported_dives(struct divelog *import_log, int flags,
/* The remaining dives in import_log->dives are those that don't belong to
* a trip and the caller does not want them to be associated to a
* new trip. Merge them into the global table. */
sequence_changed |= merge_dive_tables(import_log->dives, NULL, divelog.dives, flags & IMPORT_PREFER_IMPORTED, NULL,
sequence_changed |= merge_dive_tables(import_log->dives.get(), NULL, divelog.dives.get(), flags & IMPORT_PREFER_IMPORTED, NULL,
dives_to_add, dives_to_remove, &start_renumbering_at);
}

View file

@ -54,7 +54,6 @@ int get_min_datafile_version();
void report_datafile_version(int version);
void clear_dive_file_data();
void clear_dive_table(struct dive_table *table);
void move_dive_table(struct dive_table *src, struct dive_table *dst);
struct dive *unregister_dive(int idx);
extern bool has_dive(unsigned int deviceid, unsigned int diveid);

View file

@ -9,15 +9,12 @@
struct divelog divelog;
// We can't use smart pointers, since this is used from C
// and it would be bold to presume that std::unique_ptr<>
// and a plain pointer have the same memory layout.
divelog::divelog() :
dives(new dive_table),
trips(new trip_table),
sites(new dive_site_table),
devices(new device_table),
filter_presets(new filter_preset_table),
dives(std::make_unique<dive_table>()),
trips(std::make_unique<trip_table>()),
sites(std::make_unique<dive_site_table>()),
devices(std::make_unique<device_table>()),
filter_presets(std::make_unique<filter_preset_table>()),
autogroup(false)
{
*dives = empty_dive_table;
@ -26,39 +23,14 @@ divelog::divelog() :
divelog::~divelog()
{
clear_dive_table(dives);
clear_trip_table(trips);
delete dives;
delete trips;
delete sites;
delete devices;
delete filter_presets;
if (dives)
clear_dive_table(dives.get());
if (trips)
clear_trip_table(trips.get());
}
divelog::divelog(divelog &&log) :
dives(new dive_table),
trips(new trip_table),
sites(new dive_site_table(std::move(*log.sites))),
devices(new device_table),
filter_presets(new filter_preset_table)
{
*dives = empty_dive_table;
*trips = empty_trip_table;
move_dive_table(log.dives, dives);
move_trip_table(log.trips, trips);
*devices = std::move(*log.devices);
*filter_presets = std::move(*log.filter_presets);
}
struct divelog &divelog::operator=(divelog &&log)
{
move_dive_table(log.dives, dives);
move_trip_table(log.trips, trips);
*sites = std::move(*log.sites);
*devices = std::move(*log.devices);
*filter_presets = std::move(*log.filter_presets);
return *this;
}
divelog::divelog(divelog &&) = default;
struct divelog &divelog::operator=(divelog &&) = default;
/* this implements the mechanics of removing the dive from the
* dive log and the trip, but doesn't deal with updating dive trips, etc */
@ -69,9 +41,9 @@ void divelog::delete_single_dive(int idx)
return;
}
struct dive *dive = dives->dives[idx];
remove_dive_from_trip(dive, trips);
remove_dive_from_trip(dive, trips.get());
unregister_dive_from_dive_site(dive);
delete_dive_from_table(dives, idx);
delete_dive_from_table(dives.get(), idx);
}
void divelog::clear()
@ -83,6 +55,6 @@ void divelog::clear()
report_info("Warning: trip table not empty in divelog::clear()!");
trips->nr = 0;
}
clear_device_table(devices);
clear_device_table(devices.get());
filter_presets->clear();
}

View file

@ -1,32 +1,33 @@
// SPDX-License-Identifier: GPL-2.0
// A structure that contains all the values we save in a divelog file
// A structure that contains all the data we store in a divelog files
#ifndef DIVELOG_H
#define DIVELOG_H
#include <memory>
struct dive_table;
struct trip_table;
class dive_site_table;
struct device_table;
struct filter_preset_table;
#include <stdbool.h>
struct divelog {
struct dive_table *dives;
struct trip_table *trips;
dive_site_table *sites;
struct device_table *devices;
struct filter_preset_table *filter_presets;
std::unique_ptr<dive_table> dives;
std::unique_ptr<trip_table> trips;
std::unique_ptr<dive_site_table> sites;
std::unique_ptr<device_table> devices;
std::unique_ptr<filter_preset_table> filter_presets;
bool autogroup;
divelog();
~divelog();
divelog(divelog &&log); // move constructor (argument is consumed).
divelog &operator=(divelog &&log); // move assignment (argument is consumed).
divelog(divelog &&); // move constructor (argument is consumed).
divelog &operator=(divelog &&); // move assignment (argument is consumed).
void delete_single_dive(int idx);
void clear();
};
extern struct divelog divelog;
#endif

View file

@ -445,7 +445,7 @@ int try_to_open_csv(std::string &mem, enum csv_format type, struct divelog *log)
break;
p = end + 1;
}
record_dive_to_table(dive, log->dives);
record_dive_to_table(dive, log->dives.get());
return 1;
}
@ -750,7 +750,7 @@ int parse_txt_file(const char *filename, const char *csv, struct divelog *log)
if (!lineptr || !*lineptr)
break;
}
record_dive_to_table(dive, log->dives);
record_dive_to_table(dive, log->dives.get());
return 1;
} else {
return 0;

View file

@ -885,7 +885,7 @@ 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[0].temperature.mkelvin = dive->dc.sample[1].temperature.mkelvin;
record_dive_to_table(dive, devdata->log->dives);
record_dive_to_table(dive, devdata->log->dives.get());
return true;
error_exit:

View file

@ -450,7 +450,7 @@ int try_to_open_liquivision(const char *, std::string &mem, struct divelog *log)
}
ptr += 4;
parse_dives(log_version, buf + ptr, buf_size - ptr, log->dives, *log->sites);
parse_dives(log_version, buf + ptr, buf_size - ptr, log->dives.get(), *log->sites);
return 1;
}

View file

@ -991,7 +991,7 @@ static void parse_settings_divecomputerid(char *line, struct git_parser_state *s
break;
line = parse_keyvalue_entry(parse_divecomputerid_keyvalue, &id, line, state);
}
create_device_node(state->log->devices, id.model.c_str(), id.serial.c_str(), id.nickname.c_str());
create_device_node(state->log->devices.get(), id.model.c_str(), id.serial.c_str(), id.nickname.c_str());
}
struct fingerprint_helper {
@ -1386,7 +1386,7 @@ static void finish_active_trip(struct git_parser_state *state)
if (trip) {
state->active_trip = NULL;
insert_trip(trip, state->log->trips);
insert_trip(trip, state->log->trips.get());
}
}
@ -1396,7 +1396,7 @@ static void finish_active_dive(struct git_parser_state *state)
if (dive) {
state->active_dive = NULL;
record_dive_to_table(dive, state->log->dives);
record_dive_to_table(dive, state->log->dives.get());
}
}
@ -1787,7 +1787,7 @@ static int parse_filter_preset(struct git_parser_state *state, const git_tree_en
git_blob_free(blob);
add_filter_preset_to_table(state->active_filter.get(), state->log->filter_presets);
add_filter_preset_to_table(state->active_filter.get(), state->log->filter_presets.get());
state->active_filter.reset();
return 0;

View file

@ -176,6 +176,6 @@ void ostctools_import(const char *file, struct divelog *log)
} else {
add_extra_data(&ostcdive->dc, "Serial", ostcdive->dc.serial);
}
record_dive_to_table(ostcdive.release(), log->dives);
sort_dive_table(log->dives);
record_dive_to_table(ostcdive.release(), log->dives.get());
sort_dive_table(log->dives.get());
}

View file

@ -178,7 +178,7 @@ void dc_settings_start(struct parser_state *state)
void dc_settings_end(struct parser_state *state)
{
create_device_node(state->log->devices,
create_device_node(state->log->devices.get(),
state->cur_settings.dc.model.c_str(),
state->cur_settings.dc.serial_nr.c_str(),
state->cur_settings.dc.nickname.c_str());
@ -217,7 +217,7 @@ void filter_preset_start(struct parser_state *state)
void filter_preset_end(struct parser_state *state)
{
add_filter_preset_to_table(state->cur_filter.get(), state->log->filter_presets);
add_filter_preset_to_table(state->cur_filter.get(), state->log->filter_presets.get());
state->cur_filter.reset();
}
@ -277,7 +277,7 @@ void dive_end(struct parser_state *state)
if (!is_dive(state)) {
free_dive(state->cur_dive);
} else {
record_dive_to_table(state->cur_dive, state->log->dives);
record_dive_to_table(state->cur_dive, state->log->dives.get());
if (state->cur_trip)
add_dive_to_trip(state->cur_dive, state->cur_trip);
}
@ -300,7 +300,7 @@ void trip_end(struct parser_state *state)
{
if (!state->cur_trip)
return;
insert_trip(state->cur_trip, state->log->trips);
insert_trip(state->cur_trip, state->log->trips.get());
state->cur_trip = NULL;
}

View file

@ -1000,14 +1000,14 @@ static QString get_dive_only_date_string(timestamp_t when)
QString get_first_dive_date_string()
{
const dive_table *dives = divelog.dives;
return dives->nr > 0 ? get_dive_only_date_string(dives->dives[0]->when) : gettextFromC::tr("no dives");
const dive_table &dives = *divelog.dives;
return dives.nr > 0 ? get_dive_only_date_string(dives.dives[0]->when) : gettextFromC::tr("no dives");
}
QString get_last_dive_date_string()
{
const dive_table *dives = divelog.dives;
return dives->nr > 0 ? get_dive_only_date_string(dives->dives[dives->nr - 1]->when) : gettextFromC::tr("no dives");
const dive_table &dives = *divelog.dives;
return dives.nr > 0 ? get_dive_only_date_string(dives.dives[dives.nr - 1]->when) : gettextFromC::tr("no dives");
}
std::string get_current_date()

View file

@ -893,8 +893,8 @@ static void save_settings(git_repository *repo, struct dir *tree)
membuffer b;
put_format(&b, "version %d\n", DATAFORMAT_VERSION);
for (int i = 0; i < nr_devices(divelog.devices); i++)
save_one_device(&b, get_device(divelog.devices, i));
for (int i = 0; i < nr_devices(divelog.devices.get()); i++)
save_one_device(&b, get_device(divelog.devices.get(), i));
/* save the fingerprint data */
for (int i = 0; i < nr_fingerprints(&fingerprint_table); i++)
save_one_fingerprint(&b, i);

View file

@ -686,8 +686,8 @@ static void save_dives_buffer(struct membuffer *b, bool select_only, bool anonym
put_format(b, "<divelog program='subsurface' version='%d'>\n<settings>\n", DATAFORMAT_VERSION);
/* save the dive computer nicknames, if any */
for (int i = 0; i < nr_devices(divelog.devices); i++) {
const struct device *d = get_device(divelog.devices, i);
for (int i = 0; i < nr_devices(divelog.devices.get()); i++) {
const struct device *d = get_device(divelog.devices.get(), i);
if (!select_only || device_used_by_selected_dive(d))
save_one_device(b, d);
}

View file

@ -936,14 +936,14 @@ static bool process_raw_buffer(device_data_t *devdata, uint32_t deviceid, std::s
bp = bp.substr(1);
if (bp[0] != '{' && bp.find("{{") != std::string::npos) {
done = false;
record_dive_to_table(dive, devdata->log->dives);
record_dive_to_table(dive, devdata->log->dives.get());
dive = uemis_start_dive(deviceid);
}
}
}
if (is_log) {
if (dive->dc.diveid) {
record_dive_to_table(dive, devdata->log->dives);
record_dive_to_table(dive, devdata->log->dives.get());
} else { /* partial dive */
free_dive(dive);
return false;
@ -970,7 +970,7 @@ static std::pair<uint32_t, uint32_t> uemis_get_divenr(uint32_t deviceid, struct
* Otherwise, use the global dive table.
*/
if (!force && !table->nr)
table = divelog.dives;
table = divelog.dives.get();
for (i = 0; i < table->nr; i++) {
struct dive *d = table->dives[i];
@ -1150,7 +1150,7 @@ static bool get_matching_dive(int idx, int &newmax, uemis_mem_status &mem_status
#if UEMIS_DEBUG & 16
do_dump_buffer_to_file(mbuf, "Dive");
#endif
mem_status = get_memory(data->log->dives, uemis_checkpoint::single_dive);
mem_status = get_memory(data->log->dives.get(), uemis_checkpoint::single_dive);
if (mem_status == uemis_mem_status::ok) {
/* if the memory isn's completely full we can try to read more dive log vs. dive details
* and the dive spots should fit into the UEMIS memory
@ -1214,7 +1214,7 @@ static bool get_matching_dive(int idx, int &newmax, uemis_mem_status &mem_status
} else {
/* At this point the memory of the UEMIS is full, let's cleanup all dive log files were
* we could not match the details to. */
do_delete_dives(data->log->dives, idx);
do_delete_dives(data->log->dives.get(), idx);
return false;
}
}
@ -1273,7 +1273,7 @@ std::string do_uemis_import(device_data_t *data)
param_buff[1] = "notempty";
{
auto [mindiveid, maxdiveid] = uemis_get_divenr(deviceidnr, data->log->dives, force_download);
auto [mindiveid, maxdiveid] = uemis_get_divenr(deviceidnr, data->log->dives.get(), force_download);
newmax = maxdiveid;
if (verbose)
report_info("Uemis downloader: start looking at dive nr %d", newmax);
@ -1297,7 +1297,7 @@ std::string do_uemis_import(device_data_t *data)
param_buff[2] = newmax_str.c_str();
param_buff[3].clear();
std::string mbuf = uemis_get_answer(mountpath, "getDivelogs", 3, 0, result);
mem_status = get_memory(data->log->dives, uemis_checkpoint::details);
mem_status = get_memory(data->log->dives.get(), uemis_checkpoint::details);
/* first, remove any leading garbage... this needs to start with a '{' */
std::string_view realmbuf = mbuf;
size_t pos = realmbuf.find('{');
@ -1350,7 +1350,7 @@ std::string do_uemis_import(device_data_t *data)
start = end;
/* Do some memory checking here */
mem_status = get_memory(data->log->dives, uemis_checkpoint::log);
mem_status = get_memory(data->log->dives.get(), uemis_checkpoint::log);
if (mem_status != uemis_mem_status::ok) {
#if UEMIS_DEBUG & 4
report_info("d_u_i out of memory, bailing\n");
@ -1364,7 +1364,7 @@ std::string do_uemis_import(device_data_t *data)
// Resetting to original state
filenr = 0;
max_mem_used = -1;
mem_status = get_memory(data->log->dives, uemis_checkpoint::details);
mem_status = get_memory(data->log->dives.get(), uemis_checkpoint::details);
if (uemis_get_answer(mountpath, "getDeviceId", 0, 1, result).empty())
goto bail;
if (deviceid != param_buff[0]) {
@ -1407,7 +1407,7 @@ std::string do_uemis_import(device_data_t *data)
* be deleted from the download_table.
*/
if (mem_status == uemis_mem_status::full)
do_delete_dives(data->log->dives, match_dive_and_log);
do_delete_dives(data->log->dives.get(), match_dive_and_log);
#if UEMIS_DEBUG & 4
report_info("d_u_i out of memory, bailing instead of processing\n");
#endif