mirror of
				https://github.com/subsurface/subsurface.git
				synced 2025-02-19 22:16:15 +00:00 
			
		
		
		
	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:
		
							parent
							
								
									bfb54aa581
								
							
						
					
					
						commit
						cc39f709ce
					
				
					 35 changed files with 289 additions and 308 deletions
				
			
		|  | @ -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.
 | ||||||
|  |  | ||||||
|  | @ -15,9 +15,9 @@ 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
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // Multiple trips, dives and dive sites that have to be added for a command
 | // Multiple trips, dives and dive sites that have to be added for a command
 | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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++; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -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...
 | ||||||
|  |  | ||||||
							
								
								
									
										53
									
								
								core/dive.h
									
										
									
									
									
								
							
							
						
						
									
										53
									
								
								core/dive.h
									
										
									
									
									
								
							|  | @ -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); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|  |  | ||||||
|  | @ -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]) | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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 */ | ||||||
|  |  | ||||||
|  | @ -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,57 +898,63 @@ 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) { | ||||||
| 			from_chars(val, max_divenr); | 			// Is log
 | ||||||
| 			dive->dc.diveid = max_divenr; | 			if (tag == "object_id") { | ||||||
|  | 				from_chars(val, 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); |  | ||||||
| 			} | 			} | ||||||
|  | 			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 | #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 | #endif | ||||||
| 		} else if (dive) { | 			} else if (non_owned_dive) { | ||||||
| 			parse_tag(dive, tag, val); | 				parse_tag(non_owned_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); |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	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; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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(©PasteDive, 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; | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue