From cc39f709ce1d89dd184f6c2237f18c7cd747aa77 Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Thu, 16 May 2024 20:11:21 +0200 Subject: [PATCH] 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 --- commands/command_divelist.cpp | 6 +- commands/command_divelist.h | 6 +- commands/command_edit.cpp | 4 +- commands/command_edit.h | 2 +- core/cochran.cpp | 13 ++-- core/datatrak.cpp | 9 ++- core/dive.cpp | 78 ++++++++++------------ core/dive.h | 53 +++++++-------- core/divecomputer.cpp | 25 +++++--- core/divecomputer.h | 26 ++++---- core/divelist.cpp | 12 ++-- core/import-cobalt.cpp | 2 +- core/import-csv.cpp | 14 ++-- core/import-divinglog.cpp | 4 +- core/import-seac.cpp | 4 +- core/import-shearwater.cpp | 8 +-- core/libdivecomputer.cpp | 10 +-- core/liquivision.cpp | 14 ++-- core/load-git.cpp | 41 +++++------- core/ostctools.cpp | 2 +- core/owning_ptrs.h | 8 --- core/parse-xml.cpp | 13 ++-- core/parse.cpp | 19 +++--- core/parse.h | 2 +- core/uemis-downloader.cpp | 103 ++++++++++++++++-------------- desktop-widgets/diveplanner.cpp | 2 +- desktop-widgets/diveplanner.h | 4 +- desktop-widgets/mainwindow.cpp | 3 +- desktop-widgets/profilewidget.cpp | 2 +- desktop-widgets/profilewidget.h | 2 +- mobile-widgets/qmlmanager.cpp | 4 +- qt-models/diveplannermodel.cpp | 15 ++--- smtk-import/smartrak.cpp | 26 ++++---- tests/testformatDiveGasString.cpp | 59 ++++++++++------- tests/testplan.cpp | 2 +- 35 files changed, 289 insertions(+), 308 deletions(-) diff --git a/commands/command_divelist.cpp b/commands/command_divelist.cpp index dac5663b1..08ef58d43 100644 --- a/commands/command_divelist.cpp +++ b/commands/command_divelist.cpp @@ -411,7 +411,7 @@ AddDive::AddDive(dive *d, bool autogroup, bool newNumber) currentDive = nullptr; // Get an owning pointer to a moved dive. - OwningDivePtr divePtr(move_dive(d)); + std::unique_ptr divePtr = move_dive(d); 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 // on dive-addition. @@ -494,7 +494,7 @@ ImportDives::ImportDives(struct divelog *log, int flags, const QString &source) // Add dives to the divesToAdd.dives structure divesToAdd.dives.reserve(dives_to_add.nr); for (int i = 0; i < dives_to_add.nr; ++i) { - OwningDivePtr divePtr(dives_to_add.dives[i]); + std::unique_ptr divePtr(dives_to_add.dives[i]); divePtr->selected = false; // See above in AddDive::AddDive() dive_trip *trip = divePtr->divetrip; divePtr->divetrip = nullptr; // See above in AddDive::AddDive() @@ -971,7 +971,7 @@ MergeDives::MergeDives(const QVector &dives) dive_trip *preferred_trip; 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 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 // we manually manage the selection post-command. diff --git a/commands/command_divelist.h b/commands/command_divelist.h index bb47af725..ca550811f 100644 --- a/commands/command_divelist.h +++ b/commands/command_divelist.h @@ -15,9 +15,9 @@ namespace Command { // This helper structure describes a dive that we want to add. struct DiveToAdd { - OwningDivePtr dive; // Dive to add - dive_trip *trip; // Trip the dive belongs to, may be null - dive_site *site; // Site the dive is associated with, may be null + std::unique_ptr dive; // Dive to add + dive_trip *trip; // Trip the dive belongs to, may be null + dive_site *site; // Site the dive is associated with, may be null }; // Multiple trips, dives and dive sites that have to be added for a command diff --git a/commands/command_edit.cpp b/commands/command_edit.cpp index 48d34fdee..a4076f1f5 100644 --- a/commands/command_edit.cpp +++ b/commands/command_edit.cpp @@ -797,7 +797,6 @@ ReplanDive::ReplanDive(dive *source) : d(current_dive), when(0), maxdepth({0}), meandepth({0}), - dc({ 0 }), notes(nullptr), surface_pressure({0}), duration({0}), @@ -885,8 +884,7 @@ EditProfile::EditProfile(const dive *source, int dcNr, EditProfileType type, int maxdepth({0}), meandepth({0}), dcmaxdepth({0}), - duration({0}), - dc({ 0 }) + duration({0}) { const struct divecomputer *sdc = get_dive_dc_const(source, dcNr); if (!sdc) diff --git a/commands/command_edit.h b/commands/command_edit.h index deab84252..bc1abd129 100644 --- a/commands/command_edit.h +++ b/commands/command_edit.h @@ -465,7 +465,7 @@ public: EditDive(dive *oldDive, dive *newDive, dive_site *createDs, dive_site *editDs, location_t dsLocation); // Takes ownership of newDive private: dive *oldDive; // Dive that is going to be overwritten - OwningDivePtr newDive; // New data + std::unique_ptr newDive; // New data dive_site *newDiveSite; int changedFields; diff --git a/core/cochran.cpp b/core/cochran.cpp index 4d8243e93..5af62a8dd 100644 --- a/core/cochran.cpp +++ b/core/cochran.cpp @@ -606,7 +606,6 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod, struct dive_table *table) { unsigned char *buf = (unsigned char *)malloc(size); - struct dive *dive; struct divecomputer *dc; struct tm tm = {0}; @@ -666,7 +665,7 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod, puts("\nSample Data\n"); #endif - dive = alloc_dive(); + auto dive = std::make_unique(); dc = &dive->dc; unsigned char *log = (buf + 0x4914); @@ -678,7 +677,7 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod, cylinder_t cyl; dc->model = "Gemini"; 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 + log[CMD_O2_PERCENT + 1]) * 10; 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 for (g = 0; g < 2; g++) { 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 + log[CMD_O2_PERCENT + g * 2 + 1]) * 10; 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 for (g = 0; g < 4; g++) { cylinder_t cyl; - fill_default_cylinder(dive, &cyl); + fill_default_cylinder(dive.get(), &cyl); cyl.gasmix.o2.permille = (log[EMC_O2_PERCENT + g * 2] / 256 + 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) 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, &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; } - record_dive_to_table(dive, table); + record_dive_to_table(dive.release(), table); free(buf); } diff --git a/core/datatrak.cpp b/core/datatrak.cpp index 8485d6acf..006cb4d77 100644 --- a/core/datatrak.cpp +++ b/core/datatrak.cpp @@ -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. while ((i < numdives) && (runner < maxbuf)) { - struct dive *ptdive = alloc_dive(); + auto ptdive = std::make_unique(); - 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()) - wlog_compl_parser(wl_mem, ptdive, i); + wlog_compl_parser(wl_mem, ptdive.get(), i); if (runner == NULL) { report_error("%s", translate("gettextFromC", "Error: no dive")); - free(ptdive); rc = 1; goto out; } else { - record_dive_to_table(ptdive, log->dives.get()); + record_dive_to_table(ptdive.release(), log->dives.get()); } i++; } diff --git a/core/dive.cpp b/core/dive.cpp index e8f4f67b1..a91d0d455 100644 --- a/core/dive.cpp +++ b/core/dive.cpp @@ -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); +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 * for each sample that can have any sensor, plus a possible @@ -163,18 +174,6 @@ int dive_getUniqID() 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 */ 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) break; sdc = sdc->next; - ddc->next = (divecomputer *)calloc(1, sizeof(struct divecomputer)); + ddc->next = new divecomputer; ddc = ddc->next; } ddc->next = NULL; @@ -235,12 +234,6 @@ static void free_dive_structures(struct dive *d) 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; * in order not to leak memory, we need to free those . * copy_dive doesn't play with the divetrip and forward/backward pointers @@ -250,7 +243,7 @@ void clear_dive(struct dive *d) if (!d) return; free_dive_structures(d); - memset(d, 0, sizeof(struct dive)); + *d = 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; * this allows us to create a dive on the stack and then * add it to the divelist. */ -struct dive *move_dive(struct dive *s) +struct std::unique_ptr move_dive(struct dive *s) { - struct dive *dive = alloc_dive(); - *dive = *s; // so all the pointers in dive point to the things s pointed to - memset(s, 0, sizeof(struct dive)); // and now the pointers in s are gone - return dive; + auto d = std::make_unique(); + std::swap(*s, *d); + return d; } #define CONDITIONAL_COPY_STRING(_component) \ @@ -1300,7 +1292,7 @@ struct dive *fixup_dive(struct dive *dive) const weightsystem_t &ws = dive->weightsystems.weightsystems[i]; 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... */ if (!dive->id) 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))) { *p = check->next; check->next = NULL; - free_dc(check); + delete check; continue; } p = &check->next; @@ -2502,7 +2494,7 @@ static void interleave_dive_computers(struct dive *d, struct divecomputer *res, a = a->next; if (!a) break; - res->next = (divecomputer *)calloc(1, sizeof(struct divecomputer)); + res->next = new divecomputer; res = res->next; } while (res); } @@ -2542,7 +2534,7 @@ static void join_dive_computers(struct dive *d, struct divecomputer *res, while (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); 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 *res = alloc_dive(); + struct dive *res = new dive; 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 static struct dive *create_new_copy(const struct dive *from) { - struct dive *to = alloc_dive(); - int id; + struct dive *to = new dive; - // 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. - id = to->id; + int id = to->id; copy_dive(from, to); to->id = id; return to; @@ -3049,11 +3040,10 @@ void set_git_prefs(const char *prefs) /* clones a dive and moves given dive computer to front */ struct dive *make_first_dc(const struct dive *d, int dc_number) { - struct dive *res; struct divecomputer *dc, *newdc, *old_dc; /* copy the dive */ - res = alloc_dive(); + dive *res = new dive; copy_dive(d, res); /* 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; if (num == 0) { - /* remove the first one, so copy the second one in place of the first and free the second one - * be careful about freeing the no longer needed structures - since we copy things around we can't use free_dc()*/ + /* During our move to C++, copy the divecomputer instead of moving the internals. + * Yes, this is "inefficient", but I don't care. Will be removed anyways. */ struct divecomputer *fdc = d->dc.next; free_dc_contents(&d->dc); - memcpy(&d->dc, fdc, sizeof(struct divecomputer)); - free(fdc); + copy_dc(fdc, &d->dc); + delete fdc; } else { struct divecomputer *pdc = &d->dc; 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) { struct divecomputer *dc = pdc->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 */ struct dive *clone_delete_divecomputer(const struct dive *d, int dc_number) { - struct dive *res; - /* copy the dive */ - res = alloc_dive(); + dive *res = new dive; copy_dive(d, res); /* 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) { // Copy the dive, but only using the selected dive computer - *out2 = alloc_dive(); + *out2 = new dive; copy_dive_onedc(src, srcdc, *out2); // This will also make fixup_dive() to allocate a new dive id... diff --git a/core/dive.h b/core/dive.h index 8ffdf60f4..2a54526b8 100644 --- a/core/dive.h +++ b/core/dive.h @@ -25,37 +25,40 @@ struct full_text_cache; struct event; struct trip_table; struct dive { - struct dive_trip *divetrip; - timestamp_t when; - struct dive_site *dive_site; - char *notes; - char *diveguide, *buddy; - struct cylinder_table cylinders; - struct weightsystem_table weightsystems; - char *suit; - int number; - int rating; - int wavesize, current, visibility, surge, chill; /* 0 - 5 star ratings */ - int sac, otu, cns, maxcns; + struct dive_trip *divetrip = nullptr; + timestamp_t when = 0; + struct dive_site *dive_site = nullptr; + char *notes = nullptr; + char *diveguide = nullptr, *buddy = nullptr; + struct cylinder_table cylinders = { }; + struct weightsystem_table weightsystems = { }; + char *suit = nullptr; + int number = 0; + int rating = 0; + int wavesize = 0, current = 0, visibility = 0, surge = 0, chill = 0; /* 0 - 5 star ratings */ + int sac = 0, otu = 0, cns = 0, maxcns = 0; /* Calculated based on dive computer data */ temperature_t mintemp, maxtemp, watertemp, airtemp; depth_t maxdepth, meandepth; pressure_t surface_pressure; duration_t duration; - int salinity; // kg per 10000 l - int user_salinity; // water density reflecting a user-specified type + int salinity = 0; // kg per 10000 l + 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; - int id; // unique ID for this dive - struct picture_table pictures; - unsigned char git_id[20]; - bool notrip; /* Don't autogroup this dive to a trip */ - bool selected; - bool hidden_by_filter; - struct full_text_cache *full_text; /* word cache for full text search */ - bool invalid; + int id = 0; // unique ID for this dive + struct picture_table pictures = { }; + unsigned char git_id[20] = {}; + bool notrip = false; /* Don't autogroup this dive to a trip */ + bool selected = false; + bool hidden_by_filter = false; + struct full_text_cache *full_text = nullptr; /* word cache for full text search */ + bool invalid = false; + + dive(); + ~dive(); }; /* 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 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 clear_dive(struct dive *dive); 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 struct dive *move_dive(struct dive *s); +extern struct std::unique_ptr move_dive(struct dive *s); extern int legacy_format_o2pressures(const struct dive *dive, const struct divecomputer *dc); diff --git a/core/divecomputer.cpp b/core/divecomputer.cpp index 6546af27e..204162f75 100644 --- a/core/divecomputer.cpp +++ b/core/divecomputer.cpp @@ -11,6 +11,15 @@ #include #include +divecomputer::divecomputer() +{ +} + +divecomputer::~divecomputer() +{ + free_dc_contents(this); +} + /* * 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 - * the structure itself. For all remainding dcs in the list, free data *and* structures. */ +static void free_dc(struct divecomputer *dc) +{ + delete dc; +} + +/* The first divecomputer is embedded in the dive structure. Ignore it. + * For all remainding dcs in the list, free data and structures. */ void free_dive_dcs(struct divecomputer *dc) { - free_dc_contents(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); } -void free_dc(struct divecomputer *dc) -{ - free_dc_contents(dc); - free(dc); -} - static const char *planner_dc_name = "planned dive"; bool is_dc_planner(const struct divecomputer *dc) diff --git a/core/divecomputer.h b/core/divecomputer.h index f4ba23fce..9a08d9a88 100644 --- a/core/divecomputer.h +++ b/core/divecomputer.h @@ -26,25 +26,27 @@ struct sample; * A deviceid or diveid of zero is assumed to be "no ID". */ struct divecomputer { - timestamp_t when; + timestamp_t when = 0; duration_t duration, surfacetime, last_manual_time; depth_t maxdepth, meandepth; temperature_t airtemp, watertemp; pressure_t surface_pressure; - enum divemode_t divemode; // dive computer type: OC(default) or CCR - uint8_t no_o2sensors; // rebreathers: number of O2 sensors used - int salinity; // kg per 10000 l - const char *model, *serial, *fw_version; - uint32_t deviceid, diveid; - int samples, alloc_samples; - struct sample *sample; - struct event *events; - struct extra_data *extra_data; - struct divecomputer *next; + enum divemode_t divemode = OC; // dive computer type: OC(default) or CCR + uint8_t no_o2sensors = 0; // rebreathers: number of O2 sensors used + int salinity = 0; // kg per 10000 l + const char *model = nullptr, *serial = nullptr, *fw_version = nullptr; + uint32_t deviceid = 0, diveid = 0; + int samples = 0, alloc_samples = 0; + struct sample *sample = nullptr; + struct event *events = nullptr; + struct extra_data *extra_data = nullptr; + struct divecomputer *next = nullptr; + + divecomputer(); + ~divecomputer(); }; extern void fake_dc(struct divecomputer *dc); -extern void free_dc(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 int get_depth_at_time(const struct divecomputer *dc, unsigned int time); diff --git a/core/divelist.cpp b/core/divelist.cpp index badae34f1..a48f83663 100644 --- a/core/divelist.cpp +++ b/core/divelist.cpp @@ -687,6 +687,10 @@ int comp_dives(const struct dive *a, const struct dive *b) } /* Dive table functions */ +static void free_dive(dive *d) +{ + delete d; +} static MAKE_GROW_TABLE(dive_table, struct dive *, dives) MAKE_GET_INSERTION_INDEX(dive_table, struct dive *, dives, dive_less_than) 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 */ 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); } @@ -818,7 +822,7 @@ static void merge_imported_dives(struct dive_table *table) unregister_dive_from_trip(dive); /* Overwrite the first of the two dives and remove the second */ - free_dive(prev); + delete prev; table->dives[i - 1] = merged; 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) { if (try_to_merge_into(dive_to_add, j - 1, dives_to, prefer_imported, dives_to_add, dives_to_remove)) { - free_dive(dive_to_add); + delete dive_to_add; last_merged_into = j - 1; (*num_merged)++; 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) { if (try_to_merge_into(dive_to_add, j, dives_to, prefer_imported, dives_to_add, dives_to_remove)) { - free_dive(dive_to_add); + delete dive_to_add; last_merged_into = j; (*num_merged)++; continue; diff --git a/core/import-cobalt.cpp b/core/import-cobalt.cpp index afb2fc604..98954209f 100644 --- a/core/import-cobalt.cpp +++ b/core/import-cobalt.cpp @@ -181,7 +181,7 @@ static int cobalt_dive(void *param, int, char **data, char **) if (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_site); diff --git a/core/import-csv.cpp b/core/import-csv.cpp index 940d8428a..5b30c5fc2 100644 --- a/core/import-csv.cpp +++ b/core/import-csv.cpp @@ -401,7 +401,6 @@ int try_to_open_csv(std::string &mem, enum csv_format type, struct divelog *log) char *header[8]; int i, time; timestamp_t date; - struct dive *dive; struct divecomputer *dc; 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) return 0; - dive = alloc_dive(); + auto dive = std::make_unique(); dive->when = date; dive->number = atoi(header[1]); dc = &dive->dc; @@ -445,7 +444,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.get()); + record_dive_to_table(dive.release(), log->dives.get()); return 1; } @@ -498,7 +497,6 @@ int parse_txt_file(const char *filename, const char *csv, struct divelog *log) int prev_time = 0; cylinder_t cyl; - struct dive *dive; struct divecomputer *dc; 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_sec = ss; - dive = alloc_dive(); + auto dive = std::make_unique(); dive->when = utc_mktime(&cur_tm);; dive->dc.model = strdup("Poseidon MkVI Discovery"); 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); - if (err < 0) { - free_dive(dive); + if (err < 0) return report_error(translate("gettextFromC", "Poseidon import failed: unable to read '%s'"), csv); - } lineptr = memcsv.data(); for (;;) { struct sample *sample; @@ -750,7 +746,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.get()); + record_dive_to_table(dive.release(), log->dives.get()); return 1; } else { return 0; diff --git a/core/import-divinglog.cpp b/core/import-divinglog.cpp index d1f3bcc1a..a286cde84 100644 --- a/core/import-divinglog.cpp +++ b/core/import-divinglog.cpp @@ -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->rbt.seconds = rbt; 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 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])); 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]) utf8_string(data[3], &state->cur_dive->buddy); diff --git a/core/import-seac.cpp b/core/import-seac.cpp index 1cad1df57..451c2dfa6 100644 --- a/core/import-seac.cpp +++ b/core/import-seac.cpp @@ -70,7 +70,7 @@ static int seac_dive(void *param, int, char **data, char **) state->cur_dive->number = atoi(data[0]); // 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 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); lastgas = curgas; 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); } state->cur_sample->stopdepth.mm = 10 * sqlite3_column_int(sqlstmt, 5); diff --git a/core/import-shearwater.cpp b/core/import-shearwater.cpp index 1b7003cbf..898991bbd 100644 --- a/core/import-shearwater.cpp +++ b/core/import-shearwater.cpp @@ -61,7 +61,7 @@ static int shearwater_changes(void *param, int columns, char **data, char **) int index; bool found = false; 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) { found = true; break; @@ -75,7 +75,7 @@ static int shearwater_changes(void *param, int columns, char **data, char **) 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; } @@ -239,7 +239,7 @@ static int shearwater_dive(void *param, int, char **data, char **) long int dive_id = atol(data[11]); 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]) utf8_string(data[3], &state->cur_dive->buddy); if (data[4]) @@ -369,7 +369,7 @@ static int shearwater_cloud_dive(void *param, int, char **data, char **) state->sample_rate = 0; 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]) utf8_string(data[3], &state->cur_dive->buddy); if (data[4]) diff --git a/core/libdivecomputer.cpp b/core/libdivecomputer.cpp index 5faf00a72..3647fa253 100644 --- a/core/libdivecomputer.cpp +++ b/core/libdivecomputer.cpp @@ -809,7 +809,6 @@ static int dive_cb(const unsigned char *data, unsigned int size, dc_status_t rc; dc_parser_t *parser = NULL; device_data_t *devdata = (device_data_t *)userdata; - struct dive *dive = NULL; /* reset static data, that is only valid per dive */ stoptime = stopdepth = po2 = cns = heartbeat = 0; @@ -825,14 +824,14 @@ static int dive_cb(const unsigned char *data, unsigned int size, return true; } - dive = alloc_dive(); + auto dive = std::make_unique(); // Fill in basic fields dive->dc.model = strdup(devdata->model.c_str()); dive->dc.diveid = calculate_diveid(fingerprint, fsize); // 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) { download_error(translate("getextFromC", "Error parsing the header: %s"), errmsg(rc)); 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)) { 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()); - free_dive(dive); 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[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; error_exit: dc_parser_destroy(parser); - free_dive(dive); return true; - } #ifndef O_BINARY diff --git a/core/liquivision.cpp b/core/liquivision.cpp index 30a05f27f..4cdc3b901 100644 --- a/core/liquivision.cpp +++ b/core/liquivision.cpp @@ -136,20 +136,19 @@ static void parse_dives(int log_version, const unsigned char *buf, unsigned int unsigned int ptr = 0; unsigned char model; - struct dive *dive; struct divecomputer *dc; struct sample *sample; while (ptr < buf_size) { int i; - dive = alloc_dive(); + auto dive = std::make_unique(); memset(&sensor_ids, 0, sizeof(sensor_ids)); dc = &dive->dc; /* Just the main cylinder until we can handle the buddy cylinder porperly */ for (i = 0; i < 1; i++) { cylinder_t cyl; - fill_default_cylinder(dive, &cyl); + fill_default_cylinder(dive.get(), &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 */ 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; @@ -414,17 +413,12 @@ static void parse_dives(int log_version, const unsigned char *buf, unsigned int } // End dive - record_dive_to_table(dive, table); + record_dive_to_table(dive.release(), table); dive = NULL; // Advance ptr for next dive ptr += ps_ptr + 4; } // 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) diff --git a/core/load-git.cpp b/core/load-git.cpp index 20100ff25..4ec309a30 100644 --- a/core/load-git.cpp +++ b/core/load-git.cpp @@ -37,7 +37,7 @@ std::string saved_git_id; struct git_parser_state { git_repository *repo = nullptr; struct divecomputer *active_dc = nullptr; - struct dive *active_dive = nullptr; + std::unique_ptr active_dive; dive_trip_t *active_trip = nullptr; std::string fulltext_mode; 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) { 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); if (!ds) { ds = state->log->sites->get_by_gps(&location); if (!ds) ds = state->log->sites->create(std::string(), location); - ds->add_dive(state->active_dive); + ds->add_dive(state->active_dive.get()); } else { if (dive_site_has_gps_location(ds) && ds->location != 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) { 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) { ds = state->log->sites->get_by_name(name); if (!ds) ds = state->log->sites->create(name); - ds->add_dive(state->active_dive); + ds->add_dive(state->active_dive.get()); } else { // we already had a dive site linked to the dive 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); } 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. @@ -684,8 +684,8 @@ static struct sample *new_sample(struct git_parser_state *state) sample->pressure[0].mbar = 0; sample->pressure[1].mbar = 0; } else { - sample->sensor[0] = sanitize_sensor_id(state->active_dive, !state->o2pressure_sensor); - sample->sensor[1] = 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.get(), state->o2pressure_sensor); } 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) { - struct dive *dive = state->active_dive; - - if (dive) { - state->active_dive = NULL; - record_dive_to_table(dive, state->log->dives.get()); - } + if (state->active_dive) + record_dive_to_table(state->active_dive.release(), state->log->dives.get()); } static void create_new_dive(timestamp_t when, struct git_parser_state *state) { - state->active_dive = alloc_dive(); + state->active_dive = std::make_unique(); /* We'll fill in more data from the dive file */ state->active_dive->when = when; 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) @@ -1654,9 +1650,7 @@ static struct divecomputer *create_new_dc(struct dive *dive) dc = dc->next; /* Did we already fill that in? */ if (dc->samples || dc->model || dc->when) { - struct divecomputer *newdc = (divecomputer *)calloc(1, sizeof(*newdc)); - if (!newdc) - return NULL; + struct divecomputer *newdc = new divecomputer; dc->next = newdc; dc = newdc; } @@ -1678,7 +1672,7 @@ static int parse_divecomputer_entry(struct git_parser_state *state, const git_tr if (!blob) 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); git_blob_free(blob); 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) { - struct dive *dive = state->active_dive; git_blob *blob = git_tree_entry_blob(state->repo, entry); if (!blob) return report_error("Unable to read dive file"); if (*suffix) - dive->number = atoi(suffix + 1); + state->active_dive->number = atoi(suffix + 1); clear_weightsystem_table(&state->active_dive->weightsystems); state->o2pressure_sensor = 1; 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) { - struct dive *dive = state->active_dive; + auto &dive = state->active_dive; dive_trip_t *trip = state->active_trip; const char *name = git_tree_entry_name(entry); 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); 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; } diff --git a/core/ostctools.cpp b/core/ostctools.cpp index b3f1e4b68..2cdf1845b 100644 --- a/core/ostctools.cpp +++ b/core/ostctools.cpp @@ -48,7 +48,7 @@ void ostctools_import(const char *file, struct divelog *log) dc_family_t dc_fam; std::vector buffer(65536, 0); unsigned char uc_tmp[2]; - OwningDivePtr ostcdive(alloc_dive()); + auto ostcdive = std::make_unique(); dc_status_t rc = DC_STATUS_SUCCESS; int model, ret, i = 0, c; unsigned int serial; diff --git a/core/owning_ptrs.h b/core/owning_ptrs.h index 30367637c..3784dd688 100644 --- a/core/owning_ptrs.h +++ b/core/owning_ptrs.h @@ -9,24 +9,16 @@ #include #include -struct dive; struct dive_trip; -struct dive_site; -struct event; -void free_dive(struct dive *); void free_trip(struct dive_trip *); // 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 { void operator()(dive_trip *t) { free_trip(t); } }; // Owning pointers to dive, dive_trip, dive_site and event objects. -using OwningDivePtr = std::unique_ptr; using OwningTripPtr = std::unique_ptr; #endif diff --git a/core/parse-xml.cpp b/core/parse-xml.cpp index 88f14d0b7..304f4be62 100644 --- a/core/parse-xml.cpp +++ b/core/parse-xml.cpp @@ -657,10 +657,9 @@ static void uddf_gasswitch(const char *buffer, struct sample *sample, struct par { int idx = atoi(buffer); int seconds = sample->time.seconds; - struct dive *dive = state->cur_dive; 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) @@ -696,7 +695,7 @@ static void get_cylinderindex(const char *buffer, int16_t *i, struct parser_stat { *i = atoi(buffer); 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; } } @@ -1526,7 +1525,7 @@ static bool entry(const char *name, char *buf, struct parser_state *state) return true; } 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; } 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; // 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.he.permille = ptr[27] * 10; @@ -1974,7 +1973,7 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size, struct divelog *log) found = false; 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) { found = true; break; @@ -2225,7 +2224,7 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size, struct divelog *log) /* Measure GPS */ 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.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; default: break; diff --git a/core/parse.cpp b/core/parse.cpp index 6e98db153..a1c1a0f78 100644 --- a/core/parse.cpp +++ b/core/parse.cpp @@ -25,7 +25,6 @@ parser_state::parser_state() parser_state::~parser_state() { - free_dive(cur_dive); free_trip(cur_trip); } @@ -264,7 +263,7 @@ void dive_start(struct parser_state *state) { if (state->cur_dive) return; - state->cur_dive = alloc_dive(); + state->cur_dive = std::make_unique(); reset_dc_info(&state->cur_dive->dc, state); memset(&state->cur_tm, 0, sizeof(state->cur_tm)); state->o2pressure_sensor = 1; @@ -274,14 +273,12 @@ void dive_end(struct parser_state *state) { if (!state->cur_dive) return; - if (!is_dive(state)) { - free_dive(state->cur_dive); - } else { - record_dive_to_table(state->cur_dive, state->log->dives.get()); + if (is_dive(state)) { 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_location.lat.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[1].mbar = 0; } else { - sample->sensor[0] = sanitize_sensor_id(state->cur_dive, !state->o2pressure_sensor); - sample->sensor[1] = 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.get(), state->o2pressure_sensor); } state->cur_sample = sample; state->next_o2_sensor = 0; @@ -396,7 +393,7 @@ void divecomputer_start(struct parser_state *state) /* Did we already fill that in? */ if (dc->samples || dc->model || dc->when) { - struct divecomputer *newdc = (divecomputer *)calloc(1, sizeof(*newdc)); + struct divecomputer *newdc = new divecomputer; if (newdc) { dc->next = newdc; dc = newdc; diff --git a/core/parse.h b/core/parse.h index 98e456a1d..a2d5a1622 100644 --- a/core/parse.h +++ b/core/parse.h @@ -54,7 +54,7 @@ struct parser_state { enum import_source import_source = UNKNOWN; struct divecomputer *cur_dc = nullptr; /* non-owning */ - struct dive *cur_dive = nullptr; /* owning */ + std::unique_ptr cur_dive; /* owning */ std::unique_ptr cur_dive_site; /* owning */ location_t cur_location; struct dive_trip *cur_trip = nullptr; /* owning */ diff --git a/core/uemis-downloader.cpp b/core/uemis-downloader.cpp index cb6d86940..bbd099921 100644 --- a/core/uemis-downloader.cpp +++ b/core/uemis-downloader.cpp @@ -185,9 +185,9 @@ static void uemis_get_weight(std::string_view buffer, weightsystem_t &weight, in weight.description = translate("gettextFromC", "unknown"); } -static struct dive *uemis_start_dive(uint32_t deviceid) +static std::unique_ptr uemis_start_dive(uint32_t deviceid) { - struct dive *dive = alloc_dive(); + auto dive = std::make_unique(); dive->dc.model = strdup("Uemis Zurich"); dive->dc.deviceid = deviceid; return dive; @@ -788,7 +788,7 @@ static bool uemis_delete_dive(device_data_t *devdata, uint32_t diveid) } if (dive) { devdata->log->dives->dives[--devdata->log->dives->nr] = NULL; - free_dive(dive); + delete dive; 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; bool done = false; - bool is_log = false, is_dive = false; + bool is_log = false; std::vector sections; - struct dive *dive = NULL; + std::unique_ptr owned_dive; // in log mode + struct dive *non_owned_dive = nullptr; // in dive (non-log) mode int dive_no = 0; #if UEMIS_DEBUG & 8 @@ -831,7 +832,7 @@ static bool process_raw_buffer(device_data_t *devdata, uint32_t deviceid, std::s return false; } else if (tp == "dive") { /* this is dive detail */ - is_dive = true; + is_log = false; tp = next_token(bp); if (tp != "1.0") return false; @@ -840,7 +841,7 @@ static bool process_raw_buffer(device_data_t *devdata, uint32_t deviceid, std::s return false; } if (is_log) { - dive = uemis_start_dive(deviceid); + owned_dive = uemis_start_dive(deviceid); } else { /* remember, we don't know if this is the right entry, * so first test if this is even a valid entry */ @@ -897,57 +898,63 @@ static bool process_raw_buffer(device_data_t *devdata, uint32_t deviceid, std::s std::string(type).c_str(), std::string(val).c_str()); #endif - if (is_log && tag == "object_id") { - from_chars(val, max_divenr); - dive->dc.diveid = max_divenr; + if (is_log) { + // Is log + if (tag == "object_id") { + from_chars(val, max_divenr); + owned_dive->dc.diveid = max_divenr; #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 - } 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); } + parse_tag(owned_dive.get(), tag, val); + + if (tag == "file_content") + done = true; + /* 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 "{{" + * later in the buffer to know that the next record is complete (it could + * be a short read because of some error */ + if (done && bp.size() > 3) { + bp = bp.substr(1); + if (bp[0] != '{' && bp.find("{{") != std::string::npos) { + done = false; + record_dive_to_table(owned_dive.release(), devdata->log->dives.get()); + 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", dive->dive_site->uuid, dive->dc.diveid); + report_info("Created divesite %d for diveid : %d\n", non_owned_dive->dive_site->uuid, non_owned_dive->dc.diveid); #endif - } else if (dive) { - parse_tag(dive, tag, val); - } - if (is_log && tag == "file_content") - done = true; - /* 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 "{{" - * later in the buffer to know that the next record is complete (it could - * be a short read because of some error */ - if (done && bp.size() > 3) { - bp = bp.substr(1); - if (bp[0] != '{' && bp.find("{{") != std::string::npos) { - done = false; - record_dive_to_table(dive, devdata->log->dives.get()); - dive = uemis_start_dive(deviceid); + } else if (non_owned_dive) { + parse_tag(non_owned_dive, tag, val); } } } if (is_log) { - if (dive->dc.diveid) { - record_dive_to_table(dive, devdata->log->dives.get()); - } else { /* partial dive */ - free_dive(dive); + if (owned_dive->dc.diveid) + record_dive_to_table(owned_dive.release(), devdata->log->dives.get()); + else /* partial dive */ return false; - } } return true; } diff --git a/desktop-widgets/diveplanner.cpp b/desktop-widgets/diveplanner.cpp index a20b615c5..640d8a79e 100644 --- a/desktop-widgets/diveplanner.cpp +++ b/desktop-widgets/diveplanner.cpp @@ -537,7 +537,7 @@ void PlannerDetails::setPlanNotes(QString plan) } PlannerWidgets::PlannerWidgets() : - planned_dive(alloc_dive()), + planned_dive(std::make_unique()), dcNr(0), plannerWidget(*planned_dive, dcNr, this), plannerSettingsWidget(this) diff --git a/desktop-widgets/diveplanner.h b/desktop-widgets/diveplanner.h index 0c1cfd1c5..d47f03284 100644 --- a/desktop-widgets/diveplanner.h +++ b/desktop-widgets/diveplanner.h @@ -3,8 +3,8 @@ #define DIVEPLANNER_H #include "core/divemode.h" -#include "core/owning_ptrs.h" +#include #include #include #include @@ -91,7 +91,7 @@ public slots: void printDecoPlan(); private: - OwningDivePtr planned_dive; + std::unique_ptr planned_dive; int dcNr; public: DivePlannerWidget plannerWidget; diff --git a/desktop-widgets/mainwindow.cpp b/desktop-widgets/mainwindow.cpp index c8bee4a8b..f8e711004 100644 --- a/desktop-widgets/mainwindow.cpp +++ b/desktop-widgets/mainwindow.cpp @@ -209,7 +209,6 @@ MainWindow::MainWindow() : #ifdef NO_USERMANUAL ui.menuHelp->removeAction(ui.actionUserManual); #endif - memset(©PasteDive, 0, sizeof(copyPasteDive)); memset(&what, 0, sizeof(what)); 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) // as a starting point for the user to edit - struct dive d = { 0 }; + struct dive d; d.id = dive_getUniqID(); d.when = QDateTime::currentMSecsSinceEpoch() / 1000L + gettimezoneoffset() + 3600; d.dc.duration.seconds = 40 * 60; diff --git a/desktop-widgets/profilewidget.cpp b/desktop-widgets/profilewidget.cpp index ce12b6e55..ad9e35fd7 100644 --- a/desktop-widgets/profilewidget.cpp +++ b/desktop-widgets/profilewidget.cpp @@ -324,7 +324,7 @@ void ProfileWidget::unsetProfTissues() void ProfileWidget::editDive() { - editedDive.reset(alloc_dive()); + editedDive = std::make_unique(); copy_dive(d, editedDive.get()); // Work on a copy of the dive DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::EDIT); DivePlannerPointsModel::instance()->loadFromDive(editedDive.get(), dc); diff --git a/desktop-widgets/profilewidget.h b/desktop-widgets/profilewidget.h index 272d1a529..1bd69e4bd 100644 --- a/desktop-widgets/profilewidget.h +++ b/desktop-widgets/profilewidget.h @@ -48,7 +48,7 @@ private: void editDive(); void exitEditMode(); void rotateDC(int dir); - OwningDivePtr editedDive; + std::unique_ptr editedDive; bool placingCommand; }; diff --git a/mobile-widgets/qmlmanager.cpp b/mobile-widgets/qmlmanager.cpp index 01e6281e3..a9951ee16 100644 --- a/mobile-widgets/qmlmanager.cpp +++ b/mobile-widgets/qmlmanager.cpp @@ -1191,7 +1191,7 @@ void QMLManager::commitChanges(QString diveId, QString number, QString date, QSt report_info("state :'%s'", qPrintable(state)); } - OwningDivePtr d_ptr(alloc_dive()); // Automatically delete dive if we exit early! + auto d_ptr = std::make_unique(); // Automatically delete dive if we exit early! dive *d = d_ptr.get(); copy_dive(orig, d); @@ -1728,7 +1728,7 @@ int QMLManager::addDive() // 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) // as a starting point for the user to edit - struct dive d = { 0 }; + struct dive d; int diveId = d.id = dive_getUniqID(); d.when = QDateTime::currentMSecsSinceEpoch() / 1000L + gettimezoneoffset() + 3600; d.dc.duration.seconds = 40 * 60; diff --git a/qt-models/diveplannermodel.cpp b/qt-models/diveplannermodel.cpp index 83f02fed2..a3370c26d 100644 --- a/qt-models/diveplannermodel.cpp +++ b/qt-models/diveplannermodel.cpp @@ -1185,8 +1185,8 @@ void DivePlannerPointsModel::computeVariations(struct diveplan *original_plan, c if (!original_plan) return; - struct dive *dive = alloc_dive(); - copy_dive(d, dive); + auto dive = std::make_unique(); + copy_dive(d, dive.get()); struct decostop original[60], deeper[60], shallower[60], shorter[60], longer[60]; deco_state_cache cache, save; struct diveplan plan_copy; @@ -1214,7 +1214,7 @@ void DivePlannerPointsModel::computeVariations(struct diveplan *original_plan, c goto finish; if (my_instance != instanceCounter) 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); save.restore(&ds, false); @@ -1223,7 +1223,7 @@ void DivePlannerPointsModel::computeVariations(struct diveplan *original_plan, c last_segment->next->depth.mm += delta_depth.mm; if (my_instance != instanceCounter) 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); save.restore(&ds, false); @@ -1232,7 +1232,7 @@ void DivePlannerPointsModel::computeVariations(struct diveplan *original_plan, c last_segment->next->depth.mm -= delta_depth.mm; if (my_instance != instanceCounter) 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); save.restore(&ds, false); @@ -1240,7 +1240,7 @@ void DivePlannerPointsModel::computeVariations(struct diveplan *original_plan, c last_segment->next->time += delta_time.seconds; if (my_instance != instanceCounter) 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); save.restore(&ds, false); @@ -1248,7 +1248,7 @@ void DivePlannerPointsModel::computeVariations(struct diveplan *original_plan, c last_segment->next->time -= delta_time.seconds; if (my_instance != instanceCounter) 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); save.restore(&ds, false); @@ -1265,7 +1265,6 @@ void DivePlannerPointsModel::computeVariations(struct diveplan *original_plan, c finish: free_dps(original_plan); free(original_plan); - free_dive(dive); } void DivePlannerPointsModel::computeVariationsDone(QString variations) diff --git a/smtk-import/smartrak.cpp b/smtk-import/smartrak.cpp index 40b891c65..367ae6790 100644 --- a/smtk-import/smartrak.cpp +++ b/smtk-import/smartrak.cpp @@ -926,7 +926,7 @@ void smartrak_import(const char *file, struct divelog *log) device_data_t devdata; dc_family_t dc_fam = DC_FAMILY_NULL; unsigned char *prf_buffer, *hdr_buffer; - struct dive *smtkdive = alloc_dive(); + auto smtkdive = std::make_unique(); struct tm tm_date; size_t hdr_length, prf_length; 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) { report_error("[Error][smartrak_import]\t- %s - for dive %d", errmsg(rc), smtkdive->number); } 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) 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); 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) break; 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); } /* 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 */ 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()); 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()); - smtk_parse_relations(mdb_clon, smtkdive, (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, (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_other(smtkdive, 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, surface_list, "Surface", (char *)col[coln(SURFACEIDX)]->bind_ptr, false); - smtk_parse_bookmarks(mdb_clon, smtkdive, (char *)col[0]->bind_ptr); + smtk_parse_relations(mdb_clon, smtkdive.get(), (char *)col[0]->bind_ptr, "Type", "TypeRelation", type_list, true); + smtk_parse_relations(mdb_clon, smtkdive.get(), (char *)col[0]->bind_ptr, "Activity", "ActivityRelation", activity_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.get(), (char *)col[0]->bind_ptr, "Fish", "FishRelation", fish_list, false); + smtk_parse_other(smtkdive.get(), weather_list, "Weather", (char *)col[coln(WEATHERIDX)]->bind_ptr, false); + smtk_parse_other(smtkdive.get(), underwater_list, "Underwater", (char *)col[coln(UNDERWATERIDX)]->bind_ptr, false); + smtk_parse_other(smtkdive.get(), surface_list, "Surface", (char *)col[coln(SURFACEIDX)]->bind_ptr, false); + smtk_parse_bookmarks(mdb_clon, smtkdive.get(), (char *)col[0]->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->catalog = NULL; diff --git a/tests/testformatDiveGasString.cpp b/tests/testformatDiveGasString.cpp index a9518ee1a..af14e0068 100644 --- a/tests/testformatDiveGasString.cpp +++ b/tests/testformatDiveGasString.cpp @@ -9,14 +9,14 @@ void TestformatDiveGasString::init() void TestformatDiveGasString::test_empty() { - struct dive dive = {0}; + struct dive dive; QCOMPARE(formatDiveGasString(&dive), "air"); } void TestformatDiveGasString::test_air() { - struct dive dive = {0}; + struct dive dive; cylinder_t *cylinder = get_or_create_cylinder(&dive, 0); cylinder->start.mbar = 230000; @@ -25,8 +25,9 @@ void TestformatDiveGasString::test_air() QCOMPARE(formatDiveGasString(&dive), "air"); } -void TestformatDiveGasString::test_nitrox() { - struct dive dive = {0}; +void TestformatDiveGasString::test_nitrox() +{ + struct dive dive; cylinder_t *cylinder = get_or_create_cylinder(&dive, 0); cylinder->gasmix.o2.permille = 320; @@ -36,8 +37,9 @@ void TestformatDiveGasString::test_nitrox() { QCOMPARE(formatDiveGasString(&dive), "32%"); } -void TestformatDiveGasString::test_nitrox_not_use() { - struct dive dive = {0}; +void TestformatDiveGasString::test_nitrox_not_use() +{ + struct dive dive; cylinder_t *cylinder = get_or_create_cylinder(&dive, 0); cylinder->gasmix.o2.permille = 320; @@ -54,8 +56,9 @@ void TestformatDiveGasString::test_nitrox_not_use() { QCOMPARE(formatDiveGasString(&dive), "32%"); } -void TestformatDiveGasString::test_nitrox_deco() { - struct dive dive = {0}; +void TestformatDiveGasString::test_nitrox_deco() +{ + struct dive dive; cylinder_t *cylinder = get_or_create_cylinder(&dive, 0); cylinder->gasmix.o2.permille = 320; @@ -71,8 +74,9 @@ void TestformatDiveGasString::test_nitrox_deco() { QCOMPARE(formatDiveGasString(&dive), "32…100%"); } -void TestformatDiveGasString::test_reverse_nitrox_deco() { - struct dive dive = {0}; +void TestformatDiveGasString::test_reverse_nitrox_deco() +{ + struct dive dive; cylinder_t *cylinder = get_or_create_cylinder(&dive, 0); cylinder->gasmix.o2.permille = 1000; @@ -88,8 +92,9 @@ void TestformatDiveGasString::test_reverse_nitrox_deco() { QCOMPARE(formatDiveGasString(&dive), "27…100%"); } -void TestformatDiveGasString::test_trimix() { - struct dive dive = {0}; +void TestformatDiveGasString::test_trimix() +{ + struct dive dive; cylinder_t *cylinder = get_or_create_cylinder(&dive, 0); cylinder->gasmix.o2.permille = 210; @@ -100,8 +105,9 @@ void TestformatDiveGasString::test_trimix() { QCOMPARE(formatDiveGasString(&dive), "21/35"); } -void TestformatDiveGasString::test_trimix_deco() { - struct dive dive = {0}; +void TestformatDiveGasString::test_trimix_deco() +{ + struct dive dive; cylinder_t *cylinder = get_or_create_cylinder(&dive, 0); cylinder->gasmix.o2.permille = 210; @@ -125,8 +131,9 @@ void TestformatDiveGasString::test_trimix_deco() { QCOMPARE(formatDiveGasString(&dive), "21/35…100%"); } -void TestformatDiveGasString::test_reverse_trimix_deco() { - struct dive dive = {0}; +void TestformatDiveGasString::test_reverse_trimix_deco() +{ + struct dive dive; cylinder_t *cylinder = get_or_create_cylinder(&dive, 0); cylinder->gasmix.o2.permille = 1000; @@ -150,8 +157,9 @@ void TestformatDiveGasString::test_reverse_trimix_deco() { QCOMPARE(formatDiveGasString(&dive), "21/35…100%"); } -void TestformatDiveGasString::test_trimix_and_nitrox_same_o2() { - struct dive dive = {0}; +void TestformatDiveGasString::test_trimix_and_nitrox_same_o2() +{ + struct dive dive; cylinder_t *cylinder = get_or_create_cylinder(&dive, 0); cylinder->gasmix.o2.permille = 250; @@ -169,8 +177,9 @@ void TestformatDiveGasString::test_trimix_and_nitrox_same_o2() { QCOMPARE(formatDiveGasString(&dive), "25/25"); } -void TestformatDiveGasString::test_trimix_and_nitrox_lower_o2() { - struct dive dive = {0}; +void TestformatDiveGasString::test_trimix_and_nitrox_lower_o2() +{ + struct dive dive; cylinder_t *cylinder = get_or_create_cylinder(&dive, 0); cylinder->gasmix.o2.permille = 220; @@ -188,8 +197,9 @@ void TestformatDiveGasString::test_trimix_and_nitrox_lower_o2() { QCOMPARE(formatDiveGasString(&dive), "25/25"); } -void TestformatDiveGasString::test_ccr() { - struct dive dive = {0}; +void TestformatDiveGasString::test_ccr() +{ + struct dive dive; cylinder_t *cylinder = get_or_create_cylinder(&dive, 0); cylinder->gasmix.o2.permille = 1000; @@ -208,8 +218,9 @@ void TestformatDiveGasString::test_ccr() { QCOMPARE(formatDiveGasString(&dive), "21/35"); } -void TestformatDiveGasString::test_ccr_bailout() { - struct dive dive = {0}; +void TestformatDiveGasString::test_ccr_bailout() +{ + struct dive dive; cylinder_t *cylinder = get_or_create_cylinder(&dive, 0); cylinder->gasmix.o2.permille = 1000; diff --git a/tests/testplan.cpp b/tests/testplan.cpp index d6caaba2b..91e5ca84f 100644 --- a/tests/testplan.cpp +++ b/tests/testplan.cpp @@ -12,7 +12,7 @@ #define DEBUG 1 // testing the dive plan algorithm -static struct dive dive = { 0 }; +static struct dive dive; static struct decostop stoptable[60]; 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);