summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/cochran.c24
-rw-r--r--core/datatrak.c32
-rw-r--r--core/display.h3
-rw-r--r--core/dive.c282
-rw-r--r--core/dive.h9
-rw-r--r--core/divelist.c10
-rw-r--r--core/equipment.c117
-rw-r--r--core/equipment.h25
-rw-r--r--core/gaspressures.c9
-rw-r--r--core/import-cobalt.c14
-rw-r--r--core/import-csv.c30
-rw-r--r--core/import-divinglog.c26
-rw-r--r--core/import-shearwater.c20
-rw-r--r--core/import-suunto.c34
-rw-r--r--core/libdivecomputer.c58
-rw-r--r--core/liquivision.c7
-rw-r--r--core/load-git.c18
-rw-r--r--core/parse-xml.c92
-rw-r--r--core/parse.c3
-rw-r--r--core/parse.h1
-rw-r--r--core/planner.c80
-rw-r--r--core/plannernotes.c12
-rw-r--r--core/profile.c53
-rw-r--r--core/qthelper.cpp6
-rw-r--r--core/save-git.c2
-rw-r--r--core/save-html.c2
-rw-r--r--core/save-profiledata.c8
-rw-r--r--core/save-xml.c2
-rw-r--r--core/statistics.c24
-rw-r--r--core/subsurface-qt/DiveObjectHelper.cpp38
-rw-r--r--core/uemis.c11
31 files changed, 544 insertions, 508 deletions
diff --git a/core/cochran.c b/core/cochran.c
index 9cbc51113..632ba5bff 100644
--- a/core/cochran.c
+++ b/core/cochran.c
@@ -675,20 +675,24 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod,
case TYPE_GEMINI:
case TYPE_COMMANDER:
if (config.type == TYPE_GEMINI) {
+ cylinder_t cyl = { 0 };
dc->model = "Gemini";
dc->deviceid = buf[0x18c] * 256 + buf[0x18d]; // serial no
- fill_default_cylinder(dive, 0);
- dive->cylinder[0].gasmix.o2.permille = (log[CMD_O2_PERCENT] / 256
+ fill_default_cylinder(dive, &cyl);
+ cyl.gasmix.o2.permille = (log[CMD_O2_PERCENT] / 256
+ log[CMD_O2_PERCENT + 1]) * 10;
- dive->cylinder[0].gasmix.he.permille = 0;
+ cyl.gasmix.he.permille = 0;
+ add_to_cylinder_table(&dive->cylinders, 0, cyl);
} else {
dc->model = "Commander";
dc->deviceid = array_uint32_le(buf + 0x31e); // serial no
for (g = 0; g < 2; g++) {
- fill_default_cylinder(dive, g);
- dive->cylinder[g].gasmix.o2.permille = (log[CMD_O2_PERCENT + g * 2] / 256
+ cylinder_t cyl = { 0 };
+ fill_default_cylinder(dive, &cyl);
+ cyl.gasmix.o2.permille = (log[CMD_O2_PERCENT + g * 2] / 256
+ log[CMD_O2_PERCENT + g * 2 + 1]) * 10;
- dive->cylinder[g].gasmix.he.permille = 0;
+ cyl.gasmix.he.permille = 0;
+ add_to_cylinder_table(&dive->cylinders, g, cyl);
}
}
@@ -727,13 +731,15 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod,
dc->model = "EMC";
dc->deviceid = array_uint32_le(buf + 0x31e); // serial no
for (g = 0; g < 4; g++) {
- fill_default_cylinder(dive , g);
- dive->cylinder[g].gasmix.o2.permille =
+ cylinder_t cyl = { 0 };
+ fill_default_cylinder(dive, &cyl);
+ cyl.gasmix.o2.permille =
(log[EMC_O2_PERCENT + g * 2] / 256
+ log[EMC_O2_PERCENT + g * 2 + 1]) * 10;
- dive->cylinder[g].gasmix.he.permille =
+ cyl.gasmix.he.permille =
(log[EMC_HE_PERCENT + g * 2] / 256
+ log[EMC_HE_PERCENT + g * 2 + 1]) * 10;
+ add_to_cylinder_table(&dive->cylinders, g, cyl);
}
tm.tm_year = log[EMC_YEAR];
diff --git a/core/datatrak.c b/core/datatrak.c
index 763b8cc8b..f9f577c73 100644
--- a/core/datatrak.c
+++ b/core/datatrak.c
@@ -317,12 +317,14 @@ static unsigned char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive
*/
read_bytes(2);
if (tmp_2bytes != 0x7FFF) {
- dt_dive->cylinder[0].type.size.mliter = tmp_2bytes * 10;
- dt_dive->cylinder[0].type.description = strdup("");
- dt_dive->cylinder[0].start.mbar = 200000;
- dt_dive->cylinder[0].gasmix.he.permille = 0;
- dt_dive->cylinder[0].gasmix.o2.permille = 210;
- dt_dive->cylinder[0].manually_added = true;
+ cylinder_t cyl = { 0 };
+ cyl.type.size.mliter = tmp_2bytes * 10;
+ cyl.type.description = "";
+ cyl.start.mbar = 200000;
+ cyl.gasmix.he.permille = 0;
+ cyl.gasmix.o2.permille = 210;
+ cyl.manually_added = true;
+ add_cloned_cylinder(&dt_dive->cylinders, cyl);
}
/*
@@ -353,8 +355,8 @@ static unsigned char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive
* Air used in bar*100.
*/
read_bytes(2);
- if (tmp_2bytes != 0x7FFF && dt_dive->cylinder[0].type.size.mliter)
- dt_dive->cylinder[0].gas_used.mliter = lrint(dt_dive->cylinder[0].type.size.mliter * (tmp_2bytes / 100.0));
+ if (tmp_2bytes != 0x7FFF && dt_dive->cylinders.nr > 0)
+ dt_dive->cylinders.cylinders[0].gas_used.mliter = lrint(dt_dive->cylinders.cylinders[0].type.size.mliter * (tmp_2bytes / 100.0));
/*
* Dive Type 1 - Bit table. Subsurface don't have this record, but
@@ -529,11 +531,11 @@ static unsigned char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive
free(compl_buffer);
goto bail;
}
- if (is_nitrox)
- dt_dive->cylinder[0].gasmix.o2.permille =
+ if (is_nitrox && dt_dive->cylinders.nr > 0)
+ dt_dive->cylinders.cylinders[0].gasmix.o2.permille =
lrint(membuf[23] & 0x0F ? 20.0 + 2 * (membuf[23] & 0x0F) : 21.0) * 10;
- if (is_O2)
- dt_dive->cylinder[0].gasmix.o2.permille = membuf[23] * 10;
+ if (is_O2 && dt_dive->cylinders.nr > 0)
+ dt_dive->cylinders.cylinders[0].gasmix.o2.permille = membuf[23] * 10;
free(compl_buffer);
}
JUMP(membuf, profile_length);
@@ -547,9 +549,9 @@ static unsigned char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive
dt_dive->dc.deviceid = 0xffffffff;
create_device_node(dt_dive->dc.model, dt_dive->dc.deviceid, "", "", dt_dive->dc.model);
dt_dive->dc.next = NULL;
- if (!is_SCR && dt_dive->cylinder[0].type.size.mliter) {
- dt_dive->cylinder[0].end.mbar = dt_dive->cylinder[0].start.mbar -
- ((dt_dive->cylinder[0].gas_used.mliter / dt_dive->cylinder[0].type.size.mliter) * 1000);
+ if (!is_SCR && dt_dive->cylinders.nr > 0) {
+ dt_dive->cylinders.cylinders[0].end.mbar = dt_dive->cylinders.cylinders[0].start.mbar -
+ ((dt_dive->cylinders.cylinders[0].gas_used.mliter / dt_dive->cylinders.cylinders[0].type.size.mliter) * 1000);
}
free(devdata);
return membuf;
diff --git a/core/display.h b/core/display.h
index 3e3a9531e..8c6223be6 100644
--- a/core/display.h
+++ b/core/display.h
@@ -12,6 +12,7 @@ extern "C" {
* and one-, two- and three-minute minimums and maximums */
struct plot_info {
int nr;
+ int nr_cylinders;
int maxtime;
int meandepth, maxdepth;
int minpressure, maxpressure;
@@ -21,7 +22,7 @@ struct plot_info {
double endtempcoord;
double maxpp;
struct plot_data *entry;
- struct plot_pressure_data *pressures; /* MAX_CYLINDERS blocks of nr entries. */
+ struct plot_pressure_data *pressures; /* cylinders.nr blocks of nr entries. */
};
extern struct divecomputer *select_dc(struct dive *);
diff --git a/core/dive.c b/core/dive.c
index 6043845f6..0b68819fa 100644
--- a/core/dive.c
+++ b/core/dive.c
@@ -150,7 +150,8 @@ struct event *add_event(struct divecomputer *dc, unsigned int time, int type, in
ev->gas.mix.he.permille = (value >> 16) * 10;
/* Extension to the GASCHANGE2 format: cylinder index in 'flags' */
- if (flags > 0 && flags <= MAX_CYLINDERS)
+ /* TODO: verify that gas_index < num_cylinders. */
+ if (flags > 0)
gas_index = flags-1;
/* Fallthrough */
case SAMPLE_EVENT_GASCHANGE:
@@ -262,8 +263,8 @@ struct gasmix get_gasmix_from_event(const struct dive *dive, const struct event
struct gasmix dummy = { 0 };
if (ev && event_is_gaschange(ev)) {
int index = ev->gas.index;
- if (index >= 0 && index < MAX_CYLINDERS)
- return dive->cylinder[index].gasmix;
+ if (index >= 0 && index < dive->cylinders.nr)
+ return dive->cylinders.cylinders[index].gasmix;
return ev->gas.mix;
}
return dummy;
@@ -360,8 +361,8 @@ static void free_dive_structures(struct dive *d)
taglist_free(d->tag_list);
free_dive_dcs(&d->dc);
STRUCTURED_LIST_FREE(struct picture, d->picture_list, free_picture);
- for (int i = 0; i < MAX_CYLINDERS; i++)
- free((void *)d->cylinder[i].type.description);
+ clear_cylinder_table(&d->cylinders);
+ free(d->cylinders.cylinders);
clear_weightsystem_table(&d->weightsystems);
free(d->weightsystems.weightsystems);
}
@@ -394,14 +395,14 @@ static void copy_dive_nodc(const struct dive *s, struct dive *d)
* relevant components that are referenced through pointers,
* so all the strings and the structured lists */
*d = *s;
+ memset(&d->cylinders, 0, sizeof(d->cylinders));
memset(&d->weightsystems, 0, sizeof(d->weightsystems));
invalidate_dive_cache(d);
d->buddy = copy_string(s->buddy);
d->divemaster = copy_string(s->divemaster);
d->notes = copy_string(s->notes);
d->suit = copy_string(s->suit);
- for (int i = 0; i < MAX_CYLINDERS; i++)
- d->cylinder[i].type.description = copy_string(s->cylinder[i].type.description);
+ copy_cylinders(&s->cylinders, &d->cylinders);
copy_weights(&s->weightsystems, &d->weightsystems);
STRUCTURED_LIST_COPY(struct picture, s->picture_list, d->picture_list, copy_pl);
d->tag_list = taglist_copy(s->tag_list);
@@ -501,14 +502,7 @@ void copy_events(const struct divecomputer *s, struct divecomputer *d)
int nr_cylinders(const struct dive *dive)
{
- int nr;
-
- for (nr = MAX_CYLINDERS; nr; --nr) {
- const cylinder_t *cylinder = dive->cylinder + nr - 1;
- if (!cylinder_nodata(cylinder))
- break;
- }
- return nr;
+ return dive->cylinders.nr;
}
int nr_weightsystems(const struct dive *dive)
@@ -516,24 +510,24 @@ int nr_weightsystems(const struct dive *dive)
return dive->weightsystems.nr;
}
-void copy_cylinders(const struct dive *s, struct dive *d, bool used_only)
+void copy_cylinders(const struct cylinder_table *s, struct cylinder_table *d)
+{
+ int i;
+ clear_cylinder_table(d);
+ for (i = 0; i < s->nr; i++)
+ add_cloned_cylinder(d, s->cylinders[i]);
+}
+
+void copy_used_cylinders(const struct dive *s, struct dive *d, bool used_only)
{
- int i, j;
+ int i;
if (!s || !d)
return;
- for (i = 0, j = 0; i < MAX_CYLINDERS; i++) {
- if (!used_only || is_cylinder_used(s, i) || s->cylinder[i].cylinder_use == NOT_USED) {
- free((void *)d->cylinder[j].type.description);
- d->cylinder[j] = s->cylinder[i];
- if (d->cylinder[j].type.description)
- d->cylinder[j].type.description = strdup(d->cylinder[j].type.description);
- j++;
- }
- }
- for ( ; j < MAX_CYLINDERS; j++) {
- free((void *)d->cylinder[j].type.description);
- memset(d->cylinder + j, 0, sizeof(d->cylinder[j]));
+ clear_cylinder_table(&d->cylinders);
+ for (i = 0; i < s->cylinders.nr; i++) {
+ if (!used_only || is_cylinder_used(s, i) || s->cylinders.cylinders[i].cylinder_use == NOT_USED)
+ add_cloned_cylinder(&d->cylinders, s->cylinders.cylinders[i]);
}
}
@@ -688,8 +682,6 @@ static bool cylinder_used(const cylinder_t *cyl)
{
int start_mbar, end_mbar;
- if (cylinder_nodata(cyl))
- return false;
start_mbar = cyl->start.mbar ?: cyl->sample_start.mbar;
end_mbar = cyl->end.mbar ?: cyl->sample_end.mbar;
@@ -703,8 +695,8 @@ static int get_cylinder_used(const struct dive *dive, bool used[])
{
int i, num = 0;
- for (i = 0; i < MAX_CYLINDERS; i++) {
- used[i] = cylinder_used(dive->cylinder + i);
+ for (i = 0; i < dive->cylinders.nr; i++) {
+ used[i] = cylinder_used(dive->cylinders.cylinders + i);
if (used[i])
num++;
}
@@ -717,8 +709,8 @@ static bool has_unknown_used_cylinders(const struct dive *dive, const struct div
{
int idx;
const struct event *ev;
- bool *used_and_unknown = malloc(MAX_CYLINDERS * sizeof(bool));
- memcpy(used_and_unknown, used_cylinders, MAX_CYLINDERS * sizeof(bool));
+ bool *used_and_unknown = malloc(dive->cylinders.nr * sizeof(bool));
+ memcpy(used_and_unknown, used_cylinders, dive->cylinders.nr * sizeof(bool));
/* We know about using the O2 cylinder in a CCR dive */
if (dc->divemode == CCR) {
@@ -761,7 +753,7 @@ void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, i
bool *used_cylinders;
int num_used_cylinders;
- for (i = 0; i < MAX_CYLINDERS; i++)
+ for (i = 0; i < dive->cylinders.nr; i++)
mean[i] = duration[i] = 0;
if (!dc)
return;
@@ -771,7 +763,7 @@ void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, i
* if we don't actually know about the usage of all the
* used cylinders.
*/
- used_cylinders = malloc(MAX_CYLINDERS * sizeof(bool));
+ used_cylinders = malloc(dive->cylinders.nr * sizeof(bool));
num_used_cylinders = get_cylinder_used(dive, used_cylinders);
if (has_unknown_used_cylinders(dive, dc, used_cylinders, num_used_cylinders)) {
/*
@@ -788,7 +780,7 @@ void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, i
* For a single cylinder, use the overall mean
* and duration
*/
- for (i = 0; i < MAX_CYLINDERS; i++) {
+ for (i = 0; i < dive->cylinders.nr; i++) {
if (used_cylinders[i]) {
mean[i] = dc->meandepth.mm;
duration[i] = dc->duration.seconds;
@@ -802,8 +794,8 @@ void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, i
if (!dc->samples)
fake_dc(dc);
const struct event *ev = get_next_event(dc->events, "gaschange");
- depthtime = malloc(MAX_CYLINDERS * sizeof(*depthtime));
- memset(depthtime, 0, MAX_CYLINDERS * sizeof(*depthtime));
+ depthtime = malloc(dive->cylinders.nr * sizeof(*depthtime));
+ memset(depthtime, 0, dive->cylinders.nr * sizeof(*depthtime));
for (i = 0; i < dc->samples; i++) {
struct sample *sample = dc->sample + i;
uint32_t time = sample->time.seconds;
@@ -832,7 +824,7 @@ void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, i
lastdepth = depth;
lasttime = time;
}
- for (i = 0; i < MAX_CYLINDERS; i++) {
+ for (i = 0; i < dive->cylinders.nr; i++) {
if (duration[i])
mean[i] = (depthtime[i] + duration[i] / 2) / duration[i];
}
@@ -1004,9 +996,9 @@ static void sanitize_cylinder_info(struct dive *dive)
{
int i;
- for (i = 0; i < MAX_CYLINDERS; i++) {
- sanitize_gasmix(&dive->cylinder[i].gasmix);
- sanitize_cylinder_type(&dive->cylinder[i].type);
+ for (i = 0; i < dive->cylinders.nr; i++) {
+ sanitize_gasmix(&dive->cylinders.cylinders[i].gasmix);
+ sanitize_cylinder_type(&dive->cylinders.cylinders[i].type);
}
}
@@ -1338,8 +1330,8 @@ static void simplify_dc_pressures(struct divecomputer *dc)
/* Do we need a sensor -> cylinder mapping? */
static void fixup_start_pressure(struct dive *dive, int idx, pressure_t p)
{
- if (idx >= 0 && idx < MAX_CYLINDERS) {
- cylinder_t *cyl = dive->cylinder + idx;
+ if (idx >= 0 && idx < dive->cylinders.nr) {
+ cylinder_t *cyl = dive->cylinders.cylinders + idx;
if (p.mbar && !cyl->sample_start.mbar)
cyl->sample_start = p;
}
@@ -1347,8 +1339,8 @@ static void fixup_start_pressure(struct dive *dive, int idx, pressure_t p)
static void fixup_end_pressure(struct dive *dive, int idx, pressure_t p)
{
- if (idx >= 0 && idx < MAX_CYLINDERS) {
- cylinder_t *cyl = dive->cylinder + idx;
+ if (idx >= 0 && idx < dive->cylinders.nr) {
+ cylinder_t *cyl = dive->cylinders.cylinders + idx;
if (p.mbar && !cyl->sample_end.mbar)
cyl->sample_end = p;
}
@@ -1414,13 +1406,13 @@ static bool validate_gaschange(struct dive *dive, struct event *event)
if (event->gas.index >= 0)
return true;
- index = find_best_gasmix_match(event->gas.mix, dive->cylinder);
- if (index < 0)
+ index = find_best_gasmix_match(event->gas.mix, &dive->cylinders);
+ if (index < 0 || index >= dive->cylinders.nr)
return false;
/* Fix up the event to have the right information */
event->gas.index = index;
- event->gas.mix = dive->cylinder[index].gasmix;
+ event->gas.mix = dive->cylinders.cylinders[index].gasmix;
/* Convert to odd libdivecomputer format */
o2 = get_o2(event->gas.mix);
@@ -1544,8 +1536,8 @@ struct dive *fixup_dive(struct dive *dive)
fixup_duration(dive);
fixup_watertemp(dive);
fixup_airtemp(dive);
- for (i = 0; i < MAX_CYLINDERS; i++) {
- cylinder_t *cyl = dive->cylinder + i;
+ for (i = 0; i < dive->cylinders.nr; i++) {
+ cylinder_t *cyl = dive->cylinders.cylinders + i;
add_cylinder_description(&cyl->type);
if (same_rounded_pressure(cyl->sample_start, cyl->start))
cyl->start.mbar = 0;
@@ -1927,8 +1919,8 @@ static void merge_events(struct dive *d, struct divecomputer *res,
extern int get_cylinder_idx_by_use(const struct dive *dive, enum cylinderuse cylinder_use_type)
{
int cylinder_index;
- for (cylinder_index = 0; cylinder_index < MAX_CYLINDERS; cylinder_index++) {
- if (dive->cylinder[cylinder_index].cylinder_use == cylinder_use_type)
+ for (cylinder_index = 0; cylinder_index < dive->cylinders.nr; cylinder_index++) {
+ if (dive->cylinders.cylinders[cylinder_index].cylinder_use == cylinder_use_type)
return cylinder_index; // return the index of the cylinder with that cylinder use type
}
return -1; // negative number means cylinder_use_type not found in list of cylinders
@@ -2072,13 +2064,13 @@ void cylinder_renumber(struct dive *dive, int mapping[])
dc_cylinder_renumber(dive, dc, mapping);
}
-int same_gasmix_cylinder(cylinder_t *cyl, int cylid, struct dive *dive, bool check_unused)
+int same_gasmix_cylinder(const cylinder_t *cyl, int cylid, const struct dive *dive, bool check_unused)
{
struct gasmix mygas = cyl->gasmix;
- for (int i = 0; i < MAX_CYLINDERS; i++) {
- if (i == cylid || cylinder_none(&dive->cylinder[i]))
+ for (int i = 0; i < dive->cylinders.nr; i++) {
+ if (i == cylid)
continue;
- struct gasmix gas2 = dive->cylinder[i].gasmix;
+ struct gasmix gas2 = dive->cylinders.cylinders[i].gasmix;
if (gasmix_distance(mygas, gas2) == 0 && (is_cylinder_used(dive, i) || check_unused))
return i;
}
@@ -2104,16 +2096,16 @@ static int different_manual_pressures(const cylinder_t *a, const cylinder_t *b)
* same cylinder use (ie OC/Diluent/Oxygen), and if pressures
* have been added manually they need to match.
*/
-static int match_cylinder(const cylinder_t *cyl, const struct dive *dive, bool *used_in_a, bool *matched)
+static int match_cylinder(const cylinder_t *cyl, const struct dive *dive, const bool *used)
{
int i;
- for (i = 0; i < MAX_CYLINDERS; i++) {
+ for (i = 0; i < dive->cylinders.nr; i++) {
const cylinder_t *target;
- if (!used_in_a[i] || matched[i])
+ if (!used[i])
continue;
- target = dive->cylinder + i;
+ target = dive->cylinders.cylinders + i;
if (!same_gasmix(cyl->gasmix, target->gasmix))
continue;
if (cyl->cylinder_use != target->cylinder_use)
@@ -2128,50 +2120,15 @@ static int match_cylinder(const cylinder_t *cyl, const struct dive *dive, bool *
}
/*
- * Note: we only allocate from the end, not in holes in the middle.
- * So we don't look for empty bits, we look for "no more bits set".
- */
-static int find_unused_cylinder(bool used_map[])
-{
- int i;
-
- if (used_map[MAX_CYLINDERS - 1])
- return -1; /* Maximum number of cylinders used! */
- for (i = MAX_CYLINDERS - 1; i > 0; i--) {
- if (used_map[i - 1])
- return i;
- }
- return 0; /* Not a single cylinder used. */
-}
-
-/*
- * Copy a single cylinder
- */
-static void copy_cylinder(const cylinder_t *s, cylinder_t *d)
-{
- d->type.size.mliter = s->type.size.mliter;
- d->type.workingpressure.mbar = s->type.workingpressure.mbar;
- d->type.description = copy_string(s->type.description);
- d->gasmix = s->gasmix;
- d->start.mbar = s->start.mbar;
- d->end.mbar = s->end.mbar;
- d->sample_start.mbar = s->sample_start.mbar;
- d->sample_end.mbar = s->sample_end.mbar;
- d->depth = s->depth;
- d->manually_added = s->manually_added;
- d->gas_used.mliter = s->gas_used.mliter;
- d->deco_gas_used.mliter = s->deco_gas_used.mliter;
- d->bestmix_o2 = s->bestmix_o2;
- d->bestmix_he = s->bestmix_he;
-}
-
-/*
* We matched things up so that they have the same gasmix and
* use, but we might want to fill in any missing cylinder details
* in 'a' if we had it from 'b'.
*/
-static void merge_one_cylinder(cylinder_t *res, const cylinder_t *a, const cylinder_t *b)
+static void merge_one_cylinder(struct cylinder_table *t, const cylinder_t *a, const cylinder_t *b)
{
+ cylinder_t *res;
+ add_empty_cylinder(t);
+ res = t->cylinders + (t->nr - 1);
res->type.size.mliter = a->type.size.mliter ?
a->type.size.mliter : b->type.size.mliter;
res->type.workingpressure.mbar = a->type.workingpressure.mbar ?
@@ -2209,37 +2166,37 @@ static void merge_one_cylinder(cylinder_t *res, const cylinder_t *a, const cylin
* then try to match each of the cylinders in the other dive by the gasmix that
* is the best match and hasn't been used yet.
*
- * For each dive, a cylinder-renumbering table is returned. Currently, only
- * cylinders of dive 'b' are renumbered.
+ * For each dive, a cylinder-renumbering table is returned.
*/
static void merge_cylinders(struct dive *res, const struct dive *a, const struct dive *b,
int mapping_a[], int mapping_b[])
{
int i;
- bool *used_in_a = malloc(MAX_CYLINDERS * sizeof(bool));
- bool *used_in_b = malloc(MAX_CYLINDERS * sizeof(bool));
- bool *matched_in_a = malloc(MAX_CYLINDERS * sizeof(bool));
+ bool *used_in_a = malloc(a->cylinders.nr * sizeof(bool));
+ bool *used_in_b = malloc(b->cylinders.nr * sizeof(bool));
/* First, clear all cylinders in destination */
- memset(res->cylinder, 0, sizeof(res->cylinder));
+ clear_cylinder_table(&res->cylinders);
/* Calculate usage map of cylinders */
- for (i = 0; i < MAX_CYLINDERS; i++) {
- used_in_a[i] = !cylinder_none(a->cylinder+i) || is_cylinder_used(a, i);
- used_in_b[i] = !cylinder_none(b->cylinder+i) || is_cylinder_used(b, i);
- matched_in_a[i] = false;
+ for (i = 0; i < a->cylinders.nr; i++) {
+ used_in_a[i] = is_cylinder_used(a, i);
+ mapping_a[i] = -1;
+ }
+
+ for (i = 0; i < b->cylinders.nr; i++) {
+ used_in_b[i] = is_cylinder_used(b, i);
+ mapping_b[i] = -1;
}
/* For each cylinder in 'b', try to match up things */
- for (i = 0; i < MAX_CYLINDERS; i++) {
+ for (i = 0; i < b->cylinders.nr; i++) {
int j;
- mapping_a[i] = i;
- mapping_b[i] = -1;
if (!used_in_b[i])
continue;
- j = match_cylinder(b->cylinder+i, a, used_in_a, matched_in_a);
+ j = match_cylinder(b->cylinders.cylinders + i, a, used_in_a);
if (j < 0)
continue;
@@ -2250,54 +2207,35 @@ static void merge_cylinders(struct dive *res, const struct dive *a, const struct
*
* - save that in the mapping table
*
- * - mark it as matched so that another cylinder in 'b'
- * will no longer match
+ * - remove it from the used array so that it will not be used later
*
- * - mark 'b' as needing renumbering if the index changed
+ * - mark as needing renumbering if the index changed
*/
- merge_one_cylinder(res->cylinder + j, a->cylinder + j, b->cylinder + i);
- mapping_b[i] = j;
- matched_in_a[j] = true;
- }
-
- /* Now copy all the used cylinders from 'a' which are used, but have not been matched */
- for (i = 0; i < MAX_CYLINDERS; i++) {
- if (used_in_a[i] && !matched_in_a[i])
- copy_cylinder(a->cylinder + i, res->cylinder + i);
+ mapping_b[i] = res->cylinders.nr;
+ mapping_a[j] = res->cylinders.nr;
+ used_in_a[i] = false;
+ used_in_b[j] = false;
+ merge_one_cylinder(&res->cylinders, a->cylinders.cylinders + j, b->cylinders.cylinders + i);
+ }
+
+ /* Now copy all the used cylinders from 'a' that are used but have not been matched */
+ for (i = 0; i < a->cylinders.nr; i++) {
+ if (used_in_a[i]) {
+ mapping_a[i] = res->weightsystems.nr;
+ add_cloned_cylinder(&res->cylinders, a->cylinders.cylinders[i]);
+ }
}
- /*
- * Consider all the cylinders we matched as used, whether they
- * originally were or not (either in 'a' or 'b').
- */
- for (i = 0; i < MAX_CYLINDERS; i++)
- used_in_a[i] |= matched_in_a[i];
-
- /*
- * Go back to 'b' and remap any remaining cylinders that didn't
- * match completely.
- */
- for (i = 0; i < MAX_CYLINDERS; i++) {
- int j;
-
- /* Already remapped, or not interesting? */
- if (mapping_b[i] >= 0)
- continue;
- if (!used_in_b[i])
- continue;
-
- j = find_unused_cylinder(used_in_a);
- if (j < 0)
- continue;
-
- copy_cylinder(b->cylinder + i, res->cylinder + j);
- mapping_b[i] = j;
- used_in_a[i] = true;
+ /* Finally, copy all the used cylinders from 'b' that are used but have not been matched */
+ for (i = 0; i < b->cylinders.nr; i++) {
+ if (used_in_b[i]) {
+ mapping_b[i] = res->weightsystems.nr;
+ add_cloned_cylinder(&res->cylinders, b->cylinders.cylinders[i]);
+ }
}
free(used_in_a);
free(used_in_b);
- free(matched_in_a);
}
/* Check whether a weightsystem table contains a given weightsystem */
@@ -3022,8 +2960,8 @@ struct dive *merge_dives(const struct dive *a, const struct dive *b, int offset,
MERGE_NONZERO(res, a, b, visibility);
STRUCTURED_LIST_COPY(struct picture, a->picture_list ? a->picture_list : b->picture_list, res->picture_list, copy_pl);
taglist_merge(&res->tag_list, a->tag_list, b->tag_list);
- cylinders_map_a = malloc(MAX_CYLINDERS * sizeof(*cylinders_map_a));
- cylinders_map_b = malloc(MAX_CYLINDERS * sizeof(*cylinders_map_b));
+ cylinders_map_a = malloc(a->cylinders.nr * sizeof(*cylinders_map_a));
+ cylinders_map_b = malloc(b->cylinders.nr * sizeof(*cylinders_map_b));
merge_cylinders(res, a, b, cylinders_map_a, cylinders_map_b);
merge_equipment(res, a, b);
merge_temperatures(res, a, b);
@@ -3069,7 +3007,7 @@ static void force_fixup_dive(struct dive *d)
int old_mintemp = d->mintemp.mkelvin;
int old_maxtemp = d->maxtemp.mkelvin;
duration_t old_duration = d->duration;
- struct start_end_pressure *old_pressures = malloc(MAX_CYLINDERS * sizeof(*old_pressures));
+ struct start_end_pressure *old_pressures = malloc(d->cylinders.nr * sizeof(*old_pressures));
d->maxdepth.mm = 0;
dc->maxdepth.mm = 0;
@@ -3078,11 +3016,11 @@ static void force_fixup_dive(struct dive *d)
d->duration.seconds = 0;
d->maxtemp.mkelvin = 0;
d->mintemp.mkelvin = 0;
- for (int i = 0; i < MAX_CYLINDERS; i++) {
- old_pressures[i].start = d->cylinder[i].start;
- old_pressures[i].end = d->cylinder[i].end;
- d->cylinder[i].start.mbar = 0;
- d->cylinder[i].end.mbar = 0;
+ for (int i = 0; i < d->cylinders.nr; i++) {
+ old_pressures[i].start = d->cylinders.cylinders[i].start;
+ old_pressures[i].end = d->cylinders.cylinders[i].end;
+ d->cylinders.cylinders[i].start.mbar = 0;
+ d->cylinders.cylinders[i].end.mbar = 0;
}
fixup_dive(d);
@@ -3101,11 +3039,11 @@ static void force_fixup_dive(struct dive *d)
if (!d->duration.seconds)
d->duration = old_duration;
- for (int i = 0; i < MAX_CYLINDERS; i++) {
- if (!d->cylinder[i].start.mbar)
- d->cylinder[i].start = old_pressures[i].start;
- if (!d->cylinder[i].end.mbar)
- d->cylinder[i].end = old_pressures[i].end;
+ for (int i = 0; i < d->cylinders.nr; i++) {
+ if (!d->cylinders.cylinders[i].start.mbar)
+ d->cylinders.cylinders[i].start = old_pressures[i].start;
+ if (!d->cylinders.cylinders[i].end.mbar)
+ d->cylinders.cylinders[i].end = old_pressures[i].end;
}
free(old_pressures);
}
@@ -4063,10 +4001,14 @@ struct gasmix get_gasmix(const struct dive *dive, const struct divecomputer *dc,
const struct event *ev = *evp;
struct gasmix res;
+ /* if there is no cylinder, return air */
+ if (dive->cylinders.nr <= 0)
+ return gasmix_air;
+
if (!ev) {
/* on first invocation, get initial gas mix and first event (if any) */
int cyl = explicit_first_cylinder(dive, dc);
- res = dive->cylinder[cyl].gasmix;
+ res = dive->cylinders.cylinders[cyl].gasmix;
ev = dc ? get_next_event(dc->events, "gaschange") : NULL;
} else {
res = gasmix;
diff --git a/core/dive.h b/core/dive.h
index 132cc05d6..b1755c192 100644
--- a/core/dive.h
+++ b/core/dive.h
@@ -144,7 +144,7 @@ struct dive {
struct dive_site *dive_site;
char *notes;
char *divemaster, *buddy;
- cylinder_t cylinder[MAX_CYLINDERS];
+ struct cylinder_table cylinders;
struct weightsystem_table weightsystems;
char *suit;
int number;
@@ -183,7 +183,7 @@ extern bool dive_cache_is_valid(const struct dive *dive);
extern int get_cylinder_idx_by_use(const struct dive *dive, enum cylinderuse cylinder_use_type);
extern void cylinder_renumber(struct dive *dive, int mapping[]);
-extern int same_gasmix_cylinder(cylinder_t *cyl, int cylid, struct dive *dive, bool check_unused);
+extern int same_gasmix_cylinder(const cylinder_t *cyl, int cylid, const struct dive *dive, bool check_unused);
/* when selectively copying dive information, which parts should be copied? */
struct dive_components {
@@ -362,11 +362,12 @@ extern struct dive *try_to_merge(struct dive *a, struct dive *b, bool prefer_dow
extern struct event *clone_event(const struct event *src_ev);
extern void copy_events(const struct divecomputer *s, struct divecomputer *d);
extern void free_events(struct event *ev);
-extern void copy_cylinders(const struct dive *s, struct dive *d, bool used_only);
+extern void copy_cylinders(const struct cylinder_table *s, struct cylinder_table *d);
+extern void copy_used_cylinders(const struct dive *s, struct dive *d, bool used_only);
extern void copy_samples(const struct divecomputer *s, struct divecomputer *d);
extern bool is_cylinder_used(const struct dive *dive, int idx);
extern bool is_cylinder_prot(const struct dive *dive, int idx);
-extern void fill_default_cylinder(struct dive *dive, int idx);
+extern void fill_default_cylinder(const struct dive *dive, cylinder_t *cyl);
extern void add_gas_switch_event(struct dive *dive, struct divecomputer *dc, int time, int idx);
extern struct event *add_event(struct divecomputer *dc, unsigned int time, int type, int flags, int value, const char *name);
extern void remove_event(struct event *event);
diff --git a/core/divelist.c b/core/divelist.c
index de9509471..5eae5e638 100644
--- a/core/divelist.c
+++ b/core/divelist.c
@@ -65,15 +65,13 @@ void get_dive_gas(const struct dive *dive, int *o2_p, int *he_p, int *o2max_p)
int maxo2 = -1, maxhe = -1, mino2 = 1000;
- for (i = 0; i < MAX_CYLINDERS; i++) {
- const cylinder_t *cyl = dive->cylinder + i;
+ for (i = 0; i < dive->cylinders.nr; i++) {
+ const cylinder_t *cyl = dive->cylinders.cylinders + i;
int o2 = get_o2(cyl->gasmix);
int he = get_he(cyl->gasmix);
if (!is_cylinder_used(dive, i))
continue;
- if (cylinder_none(cyl))
- continue;
if (o2 > maxo2)
maxo2 = o2;
if (he > maxhe)
@@ -349,9 +347,9 @@ static double calculate_airuse(const struct dive *dive)
int airuse = 0;
int i;
- for (i = 0; i < MAX_CYLINDERS; i++) {
+ for (i = 0; i < dive->cylinders.nr; i++) {
pressure_t start, end;
- const cylinder_t *cyl = dive->cylinder + i;
+ const cylinder_t *cyl = dive->cylinders.cylinders + i;
start = cyl->start.mbar ? cyl->start : cyl->sample_start;
end = cyl->end.mbar ? cyl->end : cyl->sample_end;
diff --git a/core/equipment.c b/core/equipment.c
index d97ed6e4f..13e4a0486 100644
--- a/core/equipment.c
+++ b/core/equipment.c
@@ -24,6 +24,11 @@ static void free_weightsystem(weightsystem_t w)
free((void *)w.description);
}
+static void free_cylinder(cylinder_t c)
+{
+ free((void *)c.type.description);
+}
+
void copy_weights(const struct weightsystem_table *s, struct weightsystem_table *d)
{
clear_weightsystem_table(d);
@@ -41,6 +46,16 @@ MAKE_REMOVE_FROM(weightsystem_table, weightsystems)
//MAKE_REMOVE(weightsystem_table, weightsystem_t, weightsystem)
MAKE_CLEAR_TABLE(weightsystem_table, weightsystems, weightsystem)
+/* cylinder table functions */
+//static MAKE_GET_IDX(cylinder_table, cylinder_t, cylinders)
+static MAKE_GROW_TABLE(cylinder_table, cylinder_t, cylinders)
+//static MAKE_GET_INSERTION_INDEX(cylinder_table, cylinder_t, cylinders, cylinder_less_than)
+MAKE_ADD_TO(cylinder_table, cylinder_t, cylinders)
+MAKE_REMOVE_FROM(cylinder_table, cylinders)
+//MAKE_SORT(cylinder_table, cylinder_t, cylinders, comp_cylinders)
+//MAKE_REMOVE(cylinder_table, cylinder_t, cylinder)
+MAKE_CLEAR_TABLE(cylinder_table, cylinders, cylinder)
+
const char *cylinderuse_text[NUM_GAS_USE] = {
QT_TRANSLATE_NOOP("gettextFromC", "OC-gas"), QT_TRANSLATE_NOOP("gettextFromC", "diluent"), QT_TRANSLATE_NOOP("gettextFromC", "oxygen"), QT_TRANSLATE_NOOP("gettextFromC", "not used")
};
@@ -104,34 +119,27 @@ void add_cloned_weightsystem(struct weightsystem_table *t, weightsystem_t ws)
add_to_weightsystem_table(t, t->nr, w_clone);
}
-bool same_weightsystem(weightsystem_t w1, weightsystem_t w2)
-{
- return w1.weight.grams == w2.weight.grams &&
- same_string(w1.description, w2.description);
-}
-
-bool cylinder_nodata(const cylinder_t *cyl)
+/* Add a clone of a cylinder to the end of a cylinder table.
+ * Cloned in means that the description-string is copied. */
+void add_cloned_cylinder(struct cylinder_table *t, cylinder_t cyl)
{
- return !cyl->type.size.mliter &&
- !cyl->type.workingpressure.mbar &&
- !cyl->type.description &&
- !cyl->gasmix.o2.permille &&
- !cyl->gasmix.he.permille &&
- !cyl->start.mbar &&
- !cyl->end.mbar &&
- !cyl->gas_used.mliter &&
- !cyl->deco_gas_used.mliter;
+ cyl.type.description = copy_string(cyl.type.description);
+ add_to_cylinder_table(t, t->nr, cyl);
}
-static bool cylinder_nosamples(const cylinder_t *cyl)
+bool same_weightsystem(weightsystem_t w1, weightsystem_t w2)
{
- return !cyl->sample_start.mbar &&
- !cyl->sample_end.mbar;
+ return w1.weight.grams == w2.weight.grams &&
+ same_string(w1.description, w2.description);
}
-bool cylinder_none(const cylinder_t *cyl)
+bool same_cylinder(cylinder_t cyl1, cylinder_t cyl2)
{
- return cylinder_nodata(cyl) && cylinder_nosamples(cyl);
+ return same_string(cyl1.type.description, cyl2.type.description) &&
+ same_gasmix(cyl1.gasmix, cyl2.gasmix) &&
+ cyl1.start.mbar == cyl2.start.mbar &&
+ cyl1.end.mbar == cyl2.end.mbar &&
+ cyl1.cylinder_use == cyl2.cylinder_use;
}
void get_gas_string(struct gasmix gasmix, char *text, int len)
@@ -161,18 +169,16 @@ int gas_volume(const cylinder_t *cyl, pressure_t p)
return lrint(cyl->type.size.mliter * bar_to_atm(bar) / z_factor);
}
-int find_best_gasmix_match(struct gasmix mix, const cylinder_t array[])
+int find_best_gasmix_match(struct gasmix mix, const struct cylinder_table *cylinders)
{
int i;
int best = -1, score = INT_MAX;
- for (i = 0; i < MAX_CYLINDERS; i++) {
+ for (i = 0; i < cylinders->nr; i++) {
const cylinder_t *match;
int distance;
- match = array + i;
- if (cylinder_nodata(match))
- continue;
+ match = cylinders->cylinders + i;
distance = gasmix_distance(mix, match->gasmix);
if (distance >= score)
continue;
@@ -258,10 +264,7 @@ struct ws_info_t ws_info[MAX_WS_INFO] = {
void remove_cylinder(struct dive *dive, int idx)
{
- cylinder_t *cyl = dive->cylinder + idx;
- int nr = MAX_CYLINDERS - idx - 1;
- memmove(cyl, cyl + 1, nr * sizeof(*cyl));
- memset(cyl + nr, 0, sizeof(*cyl));
+ remove_from_cylinder_table(&dive->cylinders, idx);
}
void remove_weightsystem(struct dive *dive, int idx)
@@ -275,10 +278,8 @@ void reset_cylinders(struct dive *dive, bool track_gas)
{
pressure_t decopo2 = {.mbar = prefs.decopo2};
- for (int i = 0; i < MAX_CYLINDERS; i++) {
- cylinder_t *cyl = &dive->cylinder[i];
- if (cylinder_none(cyl))
- continue;
+ for (int i = 0; i < dive->cylinders.nr; i++) {
+ cylinder_t *cyl = &dive->cylinders.cylinders[i];
if (cyl->depth.mm == 0) /* if the gas doesn't give a mod, calculate based on prefs */
cyl->depth = gas_mod(cyl->gasmix, decopo2, dive, M_OR_FT(3,10));
if (track_gas)
@@ -290,7 +291,7 @@ void reset_cylinders(struct dive *dive, bool track_gas)
static void copy_cylinder_type(const cylinder_t *s, cylinder_t *d)
{
- free(d->type.description);
+ free_cylinder(*d);
d->type = s->type;
d->type.description = s->type.description ? strdup(s->type.description) : NULL;
d->gasmix = s->gasmix;
@@ -306,16 +307,54 @@ void copy_cylinder_types(const struct dive *s, struct dive *d)
if (!s || !d)
return;
- for (i = 0; i < MAX_CYLINDERS; i++)
- copy_cylinder_type(s->cylinder + i, d->cylinder + i);
+ for (i = 0; i < s->cylinders.nr && i < d->cylinders.nr; i++)
+ copy_cylinder_type(s->cylinders.cylinders + i, d->cylinders.cylinders + i);
+
+ for ( ; i < s->cylinders.nr; i++)
+ add_cloned_cylinder(&d->cylinders, s->cylinders.cylinders[i]);
+}
+
+void add_empty_cylinder(struct cylinder_table *t)
+{
+ cylinder_t cyl = { 0 };
+ cyl.type.description = strdup("");
+ add_to_cylinder_table(t, t->nr, cyl);
+}
+
+/* access to cylinders is controlled by two functions:
+ * - get_cylinder() returns the cylinder of a dive and supposes that
+ * the cylinder with the given index exists. If it doesn't, an error
+ * message is printed and NULL returned.
+ * - get_or_create_cylinder() creates an empty cylinder if it doesn't exist.
+ * Multiple cylinders might be created if the index is bigger than the
+ * number of existing cylinders
+ */
+cylinder_t *get_cylinder(const struct dive *d, int idx)
+{
+ if (idx < 0 || idx >= d->cylinders.nr) {
+ fprintf(stderr, "Warning: accessing invalid cylinder %d (%d existing)\n", idx, d->cylinders.nr);
+ return NULL;
+ }
+ return &d->cylinders.cylinders[idx];
+}
+
+cylinder_t *get_or_create_cylinder(struct dive *d, int idx)
+{
+ if (idx < 0) {
+ fprintf(stderr, "Warning: accessing invalid cylinder %d\n", idx);
+ return NULL;
+ }
+ while (idx >= d->cylinders.nr)
+ add_empty_cylinder(&d->cylinders);
+ return &d->cylinders.cylinders[idx];
}
#ifdef DEBUG_CYL
void dump_cylinders(struct dive *dive, bool verbose)
{
printf("Cylinder list:\n");
- for (int i = 0; i < MAX_CYLINDERS; i++) {
- cylinder_t *cyl = &dive->cylinder[i];
+ for (int i = 0; i < dive->cylinders; i++) {
+ cylinder_t *cyl = &dive->cylinders.cylinders[i];
printf("%02d: Type %s, %3.1fl, %3.0fbar\n", i, cyl->type.description, cyl->type.size.mliter / 1000.0, cyl->type.workingpressure.mbar / 1000.0);
printf(" Gasmix O2 %2.0f%% He %2.0f%%\n", cyl->gasmix.o2.permille / 10.0, cyl->gasmix.he.permille / 10.0);
diff --git a/core/equipment.h b/core/equipment.h
index beef30842..ce5683003 100644
--- a/core/equipment.h
+++ b/core/equipment.h
@@ -33,6 +33,17 @@ typedef struct
bool bestmix_he;
} cylinder_t;
+/* Table of cylinders. Attention: this stores cylinders,
+ * *not* pointers to cylinders. This has two crucial consequences:
+ * 1) Pointers to cylinders are not stable. They may be
+ * invalidated if the table is reallocated.
+ * 2) add_to_cylinder_table(), etc. take ownership of the
+ * cylinder. Notably of the description string. */
+struct cylinder_table {
+ int nr, allocated;
+ cylinder_t *cylinders;
+};
+
typedef struct
{
weight_t weight;
@@ -51,7 +62,6 @@ struct weightsystem_table {
weightsystem_t *weightsystems;
};
-#define MAX_CYLINDERS (20)
#define MAX_TANK_INFO (100)
#define MAX_WS_INFO (100)
@@ -59,16 +69,19 @@ extern int cylinderuse_from_text(const char *text);
extern void copy_weights(const struct weightsystem_table *s, struct weightsystem_table *d);
extern void copy_cylinder_types(const struct dive *s, struct dive *d);
extern void add_cloned_weightsystem(struct weightsystem_table *t, weightsystem_t ws);
+extern void add_empty_cylinder(struct cylinder_table *t);
+extern void add_cloned_cylinder(struct cylinder_table *t, cylinder_t cyl);
+extern cylinder_t *get_cylinder(const struct dive *d, int idx);
+extern cylinder_t *get_or_create_cylinder(struct dive *d, int idx);
extern void add_cylinder_description(const cylinder_type_t *);
extern void add_weightsystem_description(const weightsystem_t *);
extern bool same_weightsystem(weightsystem_t w1, weightsystem_t w2);
-extern bool cylinder_nodata(const cylinder_t *cyl);
-extern bool cylinder_none(const cylinder_t *cyl);
+extern bool same_cylinder(cylinder_t cyl1, cylinder_t cyl2);
extern void remove_cylinder(struct dive *dive, int idx);
extern void remove_weightsystem(struct dive *dive, int idx);
extern void reset_cylinders(struct dive *dive, bool track_gas);
extern int gas_volume(const cylinder_t *cyl, pressure_t p); /* Volume in mliter of a cylinder at pressure 'p' */
-extern int find_best_gasmix_match(struct gasmix mix, const cylinder_t array[]);
+extern int find_best_gasmix_match(struct gasmix mix, const struct cylinder_table *cylinders);
#ifdef DEBUG_CYL
extern void dump_cylinders(struct dive *dive, bool verbose);
#endif
@@ -77,6 +90,10 @@ extern void dump_cylinders(struct dive *dive, bool verbose);
extern void clear_weightsystem_table(struct weightsystem_table *);
extern void add_to_weightsystem_table(struct weightsystem_table *, int idx, weightsystem_t ws);
+/* Cylinder table functions */
+extern void clear_cylinder_table(struct cylinder_table *);
+extern void add_to_cylinder_table(struct cylinder_table *, int idx, cylinder_t cyl);
+
void get_gas_string(struct gasmix gasmix, char *text, int len);
const char *gasname(struct gasmix gasmix);
diff --git a/core/gaspressures.c b/core/gaspressures.c
index 2feeaa7d0..a69dbb295 100644
--- a/core/gaspressures.c
+++ b/core/gaspressures.c
@@ -238,7 +238,7 @@ static void fill_missing_tank_pressures(struct dive *dive, struct plot_info *pi,
if (!track_pr)
return;
- if (dive->cylinder[cyl].cylinder_use == OC_GAS)
+ if (dive->cylinders.cylinders[cyl].cylinder_use == OC_GAS)
strategy = SAC;
else
strategy = TIME;
@@ -302,7 +302,7 @@ static void fill_missing_tank_pressures(struct dive *dive, struct plot_info *pi,
last_segment = segment;
}
- if(dive->cylinder[cyl].cylinder_use == OC_GAS) {
+ if(dive->cylinders.cylinders[cyl].cylinder_use == OC_GAS) {
/* if this segment has pressure_time, then calculate a new interpolated pressure */
if (interpolate.pressure_time) {
@@ -366,7 +366,7 @@ void populate_pressure_information(struct dive *dive, struct divecomputer *dc, s
{
UNUSED(dc);
int first, last, cyl;
- cylinder_t *cylinder = dive->cylinder + sensor;
+ cylinder_t *cylinder = dive->cylinders.cylinders + sensor;
pr_track_t *track = NULL;
pr_track_t *current = NULL;
const struct event *ev, *b_ev;
@@ -374,6 +374,9 @@ void populate_pressure_information(struct dive *dive, struct divecomputer *dc, s
enum divemode_t dmode = dc->divemode;
const double gasfactor[5] = {1.0, 0.0, prefs.pscr_ratio/1000.0, 1.0, 1.0 };
+ if (sensor < 0 || sensor >= dive->cylinders.nr)
+ return;
+
/* if we have no pressure data whatsoever, this is pointless, so let's just return */
if (!cylinder->start.mbar && !cylinder->end.mbar &&
!cylinder->sample_start.mbar && !cylinder->sample_end.mbar)
diff --git a/core/import-cobalt.c b/core/import-cobalt.c
index b2c5793d7..967f7df51 100644
--- a/core/import-cobalt.c
+++ b/core/import-cobalt.c
@@ -37,20 +37,22 @@ static int cobalt_cylinders(void *param, int columns, char **data, char **column
UNUSED(columns);
UNUSED(column);
struct parser_state *state = (struct parser_state *)param;
+ cylinder_t *cyl;
cylinder_start(state);
+ cyl = &state->cur_dive->cylinders.cylinders[state->cur_dive->cylinders.nr - 1];
if (data[0])
- state->cur_dive->cylinder[state->cur_cylinder_index].gasmix.o2.permille = atoi(data[0]) * 10;
+ cyl->gasmix.o2.permille = atoi(data[0]) * 10;
if (data[1])
- state->cur_dive->cylinder[state->cur_cylinder_index].gasmix.he.permille = atoi(data[1]) * 10;
+ cyl->gasmix.he.permille = atoi(data[1]) * 10;
if (data[2])
- state->cur_dive->cylinder[state->cur_cylinder_index].start.mbar = psi_to_mbar(atoi(data[2]));
+ cyl->start.mbar = psi_to_mbar(atoi(data[2]));
if (data[3])
- state->cur_dive->cylinder[state->cur_cylinder_index].end.mbar = psi_to_mbar(atoi(data[3]));
+ cyl->end.mbar = psi_to_mbar(atoi(data[3]));
if (data[4])
- state->cur_dive->cylinder[state->cur_cylinder_index].type.size.mliter = atoi(data[4]) * 100;
+ cyl->type.size.mliter = atoi(data[4]) * 100;
if (data[5])
- state->cur_dive->cylinder[state->cur_cylinder_index].gas_used.mliter = atoi(data[5]) * 1000;
+ cyl->gas_used.mliter = atoi(data[5]) * 1000;
cylinder_end(state);
return 0;
diff --git a/core/import-csv.c b/core/import-csv.c
index 9c391025e..f34cb6802 100644
--- a/core/import-csv.c
+++ b/core/import-csv.c
@@ -509,8 +509,8 @@ int parse_txt_file(const char *filename, const char *csv, struct dive_table *tab
int prev_depth = 0, cur_sampletime = 0, prev_setpoint = -1, prev_ndl = -1;
bool has_depth = false, has_setpoint = false, has_ndl = false;
char *lineptr, *key, *value;
- int cur_cylinder_index = 0;
unsigned int prev_time = 0;
+ cylinder_t cyl;
struct dive *dive;
struct divecomputer *dc;
@@ -538,25 +538,25 @@ int parse_txt_file(const char *filename, const char *csv, struct dive_table *tab
dive->dc.divemode = CCR;
dive->dc.no_o2sensors = 2;
- dive->cylinder[cur_cylinder_index].cylinder_use = OXYGEN;
- dive->cylinder[cur_cylinder_index].type.size.mliter = 3000;
- dive->cylinder[cur_cylinder_index].type.workingpressure.mbar = 200000;
- dive->cylinder[cur_cylinder_index].type.description = strdup("3l Mk6");
- dive->cylinder[cur_cylinder_index].gasmix.o2.permille = 1000;
- cur_cylinder_index++;
-
- dive->cylinder[cur_cylinder_index].cylinder_use = DILUENT;
- dive->cylinder[cur_cylinder_index].type.size.mliter = 3000;
- dive->cylinder[cur_cylinder_index].type.workingpressure.mbar = 200000;
- dive->cylinder[cur_cylinder_index].type.description = strdup("3l Mk6");
+ cyl.cylinder_use = OXYGEN;
+ cyl.type.size.mliter = 3000;
+ cyl.type.workingpressure.mbar = 200000;
+ cyl.type.description = "3l Mk6";
+ cyl.gasmix.o2.permille = 1000;
+ add_cloned_cylinder(&dive->cylinders, cyl);
+
+ cyl.cylinder_use = DILUENT;
+ cyl.type.size.mliter = 3000;
+ cyl.type.workingpressure.mbar = 200000;
+ cyl.type.description = "3l Mk6";
value = parse_mkvi_value(memtxt.buffer, "Helium percentage");
he = atoi(value);
free(value);
value = parse_mkvi_value(memtxt.buffer, "Nitrogen percentage");
- dive->cylinder[cur_cylinder_index].gasmix.o2.permille = (100 - atoi(value) - he) * 10;
+ cyl.gasmix.o2.permille = (100 - atoi(value) - he) * 10;
free(value);
- dive->cylinder[cur_cylinder_index].gasmix.he.permille = he * 10;
- cur_cylinder_index++;
+ cyl.gasmix.he.permille = he * 10;
+ add_cloned_cylinder(&dive->cylinders, cyl);
lineptr = strstr(memtxt.buffer, "Dive started at");
while (!empty_string(lineptr) && (lineptr = strchr(lineptr, '\n'))) {
diff --git a/core/import-divinglog.c b/core/import-divinglog.c
index 98d2effbb..cd122c40a 100644
--- a/core/import-divinglog.c
+++ b/core/import-divinglog.c
@@ -18,22 +18,16 @@ static int divinglog_cylinder(void *param, int columns, char **data, char **colu
UNUSED(columns);
UNUSED(column);
struct parser_state *state = (struct parser_state *)param;
+ cylinder_t *cyl;
short dbl = 1;
//char get_cylinder_template[] = "select TankID,TankSize,PresS,PresE,PresW,O2,He,DblTank from Tank where LogID = %d";
- /*
- * Divinglog might have more cylinders than what we support. So
- * better to ignore those.
- */
-
- if (state->cur_cylinder_index >= MAX_CYLINDERS)
- return 0;
-
if (data[7] && atoi(data[7]) > 0)
dbl = 2;
cylinder_start(state);
+ cyl = &state->cur_dive->cylinders.cylinders[state->cur_dive->cylinders.nr - 1];
/*
* Assuming that we have to double the cylinder size, if double
@@ -41,18 +35,18 @@ static int divinglog_cylinder(void *param, int columns, char **data, char **colu
*/
if (data[1] && atoi(data[1]) > 0)
- state->cur_dive->cylinder[state->cur_cylinder_index].type.size.mliter = atol(data[1]) * 1000 * dbl;
+ cyl->type.size.mliter = atol(data[1]) * 1000 * dbl;
if (data[2] && atoi(data[2]) > 0)
- state->cur_dive->cylinder[state->cur_cylinder_index].start.mbar = atol(data[2]) * 1000;
+ cyl->start.mbar = atol(data[2]) * 1000;
if (data[3] && atoi(data[3]) > 0)
- state->cur_dive->cylinder[state->cur_cylinder_index].end.mbar = atol(data[3]) * 1000;
+ cyl->end.mbar = atol(data[3]) * 1000;
if (data[4] && atoi(data[4]) > 0)
- state->cur_dive->cylinder[state->cur_cylinder_index].type.workingpressure.mbar = atol(data[4]) * 1000;
+ cyl->type.workingpressure.mbar = atol(data[4]) * 1000;
if (data[5] && atoi(data[5]) > 0)
- state->cur_dive->cylinder[state->cur_cylinder_index].gasmix.o2.permille = atol(data[5]) * 10;
+ cyl->gasmix.o2.permille = atol(data[5]) * 10;
if (data[6] && atoi(data[6]) > 0)
- state->cur_dive->cylinder[state->cur_cylinder_index].gasmix.he.permille = atol(data[6]) * 10;
+ cyl->gasmix.he.permille = atol(data[6]) * 10;
cylinder_end(state);
@@ -136,8 +130,8 @@ static int divinglog_profile(void *param, int columns, char **data, char **colum
state->cur_sample->temperature.mkelvin = C_to_mkelvin(temp / 10.0f);
state->cur_sample->pressure[0].mbar = pressure * 100;
state->cur_sample->rbt.seconds = rbt;
- if (oldcyl != tank) {
- struct gasmix mix = state->cur_dive->cylinder[tank].gasmix;
+ if (oldcyl != tank && tank >= 0 && tank < state->cur_dive->cylinders.nr) {
+ struct gasmix mix = state->cur_dive->cylinders.cylinders[tank].gasmix;
int o2 = get_o2(mix);
int he = get_he(mix);
diff --git a/core/import-shearwater.c b/core/import-shearwater.c
index 4bed8ff18..cd5815c6e 100644
--- a/core/import-shearwater.c
+++ b/core/import-shearwater.c
@@ -18,6 +18,7 @@ static int shearwater_cylinders(void *param, int columns, char **data, char **co
UNUSED(columns);
UNUSED(column);
struct parser_state *state = (struct parser_state *)param;
+ cylinder_t *cyl;
int o2 = lrint(strtod_flags(data[0], NULL, 0) * 1000);
int he = lrint(strtod_flags(data[1], NULL, 0) * 1000);
@@ -28,8 +29,9 @@ static int shearwater_cylinders(void *param, int columns, char **data, char **co
o2 = 1000;
cylinder_start(state);
- state->cur_dive->cylinder[state->cur_cylinder_index].gasmix.o2.permille = o2;
- state->cur_dive->cylinder[state->cur_cylinder_index].gasmix.he.permille = he;
+ cyl = &state->cur_dive->cylinders.cylinders[state->cur_dive->cylinders.nr - 1];
+ cyl->gasmix.o2.permille = o2;
+ cyl->gasmix.he.permille = he;
cylinder_end(state);
return 0;
@@ -40,6 +42,7 @@ static int shearwater_changes(void *param, int columns, char **data, char **colu
UNUSED(columns);
UNUSED(column);
struct parser_state *state = (struct parser_state *)param;
+ cylinder_t *cyl;
if (columns != 3) {
return 1;
@@ -58,8 +61,9 @@ static int shearwater_changes(void *param, int columns, char **data, char **colu
// Find the cylinder index
int i;
bool found = false;
- for (i = 0; i < state->cur_cylinder_index; ++i) {
- if (state->cur_dive->cylinder[i].gasmix.o2.permille == o2 && state->cur_dive->cylinder[i].gasmix.he.permille == he) {
+ for (i = 0; i < state->cur_dive->cylinders.nr; ++i) {
+ const cylinder_t *cyl = &state->cur_dive->cylinders.cylinders[i];
+ if (cyl->gasmix.o2.permille == o2 && cyl->gasmix.he.permille == he) {
found = true;
break;
}
@@ -67,13 +71,13 @@ static int shearwater_changes(void *param, int columns, char **data, char **colu
if (!found) {
// Cylinder not found, creating a new one
cylinder_start(state);
- state->cur_dive->cylinder[state->cur_cylinder_index].gasmix.o2.permille = o2;
- state->cur_dive->cylinder[state->cur_cylinder_index].gasmix.he.permille = he;
+ cyl = &state->cur_dive->cylinders.cylinders[state->cur_dive->cylinders.nr - 1];
+ cyl->gasmix.o2.permille = o2;
+ cyl->gasmix.he.permille = he;
cylinder_end(state);
- i = state->cur_cylinder_index;
}
- add_gas_switch_event(state->cur_dive, get_dc(state), state->sample_rate ? atoi(data[0]) / state->sample_rate * 10 : atoi(data[0]), i);
+ add_gas_switch_event(state->cur_dive, get_dc(state), state->sample_rate ? atoi(data[0]) / state->sample_rate * 10 : atoi(data[0]), state->cur_dive->cylinders.nr - 1);
return 0;
}
diff --git a/core/import-suunto.c b/core/import-suunto.c
index ac01ba639..408128cb7 100644
--- a/core/import-suunto.c
+++ b/core/import-suunto.c
@@ -173,6 +173,7 @@ static int dm4_dive(void *param, int columns, char **data, char **column)
char get_events_template[] = "select * from Mark where DiveId = %d";
char get_tags_template[] = "select Text from DiveTag where DiveId = %d";
char get_events[64];
+ cylinder_t *cyl;
dive_start(state);
state->cur_dive->number = atoi(data[0]);
@@ -218,22 +219,23 @@ static int dm4_dive(void *param, int columns, char **data, char **column)
* TODO: handle multiple cylinders
*/
cylinder_start(state);
+ cyl = &state->cur_dive->cylinders.cylinders[state->cur_dive->cylinders.nr - 1];
if (data[22] && atoi(data[22]) > 0)
- state->cur_dive->cylinder[state->cur_cylinder_index].start.mbar = atoi(data[22]);
+ cyl->start.mbar = atoi(data[22]);
else if (data[10] && atoi(data[10]) > 0)
- state->cur_dive->cylinder[state->cur_cylinder_index].start.mbar = atoi(data[10]);
+ cyl->start.mbar = atoi(data[10]);
if (data[23] && atoi(data[23]) > 0)
- state->cur_dive->cylinder[state->cur_cylinder_index].end.mbar = (atoi(data[23]));
+ cyl->end.mbar = (atoi(data[23]));
if (data[11] && atoi(data[11]) > 0)
- state->cur_dive->cylinder[state->cur_cylinder_index].end.mbar = (atoi(data[11]));
+ cyl->end.mbar = (atoi(data[11]));
if (data[12])
- state->cur_dive->cylinder[state->cur_cylinder_index].type.size.mliter = lrint((strtod_flags(data[12], NULL, 0)) * 1000);
+ cyl->type.size.mliter = lrint((strtod_flags(data[12], NULL, 0)) * 1000);
if (data[13])
- state->cur_dive->cylinder[state->cur_cylinder_index].type.workingpressure.mbar = (atoi(data[13]));
+ cyl->type.workingpressure.mbar = (atoi(data[13]));
if (data[20])
- state->cur_dive->cylinder[state->cur_cylinder_index].gasmix.o2.permille = atoi(data[20]) * 10;
+ cyl->gasmix.o2.permille = atoi(data[20]) * 10;
if (data[21])
- state->cur_dive->cylinder[state->cur_cylinder_index].gasmix.he.permille = atoi(data[21]) * 10;
+ cyl->gasmix.he.permille = atoi(data[21]) * 10;
cylinder_end(state);
if (data[14])
@@ -324,25 +326,27 @@ static int dm5_cylinders(void *param, int columns, char **data, char **column)
UNUSED(columns);
UNUSED(column);
struct parser_state *state = (struct parser_state *)param;
+ cylinder_t *cyl;
cylinder_start(state);
+ cyl = &state->cur_dive->cylinders.cylinders[state->cur_dive->cylinders.nr - 1];
if (data[7] && atoi(data[7]) > 0 && atoi(data[7]) < 350000)
- state->cur_dive->cylinder[state->cur_cylinder_index].start.mbar = atoi(data[7]);
+ cyl->start.mbar = atoi(data[7]);
if (data[8] && atoi(data[8]) > 0 && atoi(data[8]) < 350000)
- state->cur_dive->cylinder[state->cur_cylinder_index].end.mbar = (atoi(data[8]));
+ cyl->end.mbar = (atoi(data[8]));
if (data[6]) {
/* DM5 shows tank size of 12 liters when the actual
* value is 0 (and using metric units). So we just use
* the same 12 liters when size is not available */
- if (strtod_flags(data[6], NULL, 0) == 0.0 && state->cur_dive->cylinder[state->cur_cylinder_index].start.mbar)
- state->cur_dive->cylinder[state->cur_cylinder_index].type.size.mliter = 12000;
+ if (strtod_flags(data[6], NULL, 0) == 0.0 && cyl->start.mbar)
+ cyl->type.size.mliter = 12000;
else
- state->cur_dive->cylinder[state->cur_cylinder_index].type.size.mliter = lrint((strtod_flags(data[6], NULL, 0)) * 1000);
+ cyl->type.size.mliter = lrint((strtod_flags(data[6], NULL, 0)) * 1000);
}
if (data[2])
- state->cur_dive->cylinder[state->cur_cylinder_index].gasmix.o2.permille = atoi(data[2]) * 10;
+ cyl->gasmix.o2.permille = atoi(data[2]) * 10;
if (data[3])
- state->cur_dive->cylinder[state->cur_cylinder_index].gasmix.he.permille = atoi(data[3]) * 10;
+ cyl->gasmix.he.permille = atoi(data[3]) * 10;
cylinder_end(state);
return 0;
}
diff --git a/core/libdivecomputer.c b/core/libdivecomputer.c
index 9787ab826..d3e5a115d 100644
--- a/core/libdivecomputer.c
+++ b/core/libdivecomputer.c
@@ -112,7 +112,9 @@ static int parse_gasmixes(device_data_t *devdata, struct dive *dive, dc_parser_t
}
bool no_volume = true;
- for (i = 0; i < MAX_CYLINDERS && (i < ngases || i < ntanks); i++) {
+ clear_cylinder_table(&dive->cylinders);
+ for (i = 0; i < ngases || i < ntanks; i++) {
+ cylinder_t cyl = { 0 };
if (i < ngases) {
dc_gasmix_t gasmix = { 0 };
int o2, he;
@@ -139,27 +141,22 @@ static int parse_gasmixes(device_data_t *devdata, struct dive *dive, dc_parser_t
}
he = 0;
}
- dive->cylinder[i].gasmix.o2.permille = o2;
- dive->cylinder[i].gasmix.he.permille = he;
- } else {
- dive->cylinder[i].gasmix.o2.permille = 0;
- dive->cylinder[i].gasmix.he.permille = 0;
+ cyl.gasmix.o2.permille = o2;
+ cyl.gasmix.he.permille = he;
}
if (i < ntanks) {
dc_tank_t tank = { 0 };
rc = dc_parser_get_field(parser, DC_FIELD_TANK, i, &tank);
if (rc == DC_STATUS_SUCCESS) {
- cylinder_t *cyl = dive->cylinder + i;
-
- cyl->type.size.mliter = lrint(tank.volume * 1000);
- cyl->type.workingpressure.mbar = lrint(tank.workpressure * 1000);
+ cyl.type.size.mliter = lrint(tank.volume * 1000);
+ cyl.type.workingpressure.mbar = lrint(tank.workpressure * 1000);
- cyl->cylinder_use = OC_GAS;
+ cyl.cylinder_use = OC_GAS;
if (tank.type & DC_TANKINFO_CC_O2)
- cyl->cylinder_use = OXYGEN;
+ cyl.cylinder_use = OXYGEN;
if (tank.type & DC_TANKINFO_CC_DILUENT)
- cyl->cylinder_use = DILUENT;
+ cyl.cylinder_use = DILUENT;
if (tank.type & DC_TANKINFO_IMPERIAL) {
if (same_string(devdata->model, "Suunto EON Steel")) {
@@ -169,13 +166,13 @@ static int parse_gasmixes(device_data_t *devdata, struct dive *dive, dc_parser_t
* First, the pressures are off by a constant factor. WTF?
* Then we can round the wet sizes so we get to multiples of 10
* for cuft sizes (as that's all that you can enter) */
- dive->cylinder[i].type.workingpressure.mbar = lrint(
- dive->cylinder[i].type.workingpressure.mbar * 206.843 / 206.7 );
+ cyl.type.workingpressure.mbar = lrint(
+ cyl.type.workingpressure.mbar * 206.843 / 206.7 );
char name_buffer[17];
- int rounded_size = lrint(ml_to_cuft(gas_volume(&dive->cylinder[i],
- dive->cylinder[i].type.workingpressure)));
+ int rounded_size = lrint(ml_to_cuft(gas_volume(&cyl,
+ cyl.type.workingpressure)));
rounded_size = (int)((rounded_size + 5) / 10) * 10;
- switch (dive->cylinder[i].type.workingpressure.mbar) {
+ switch (cyl.type.workingpressure.mbar) {
case 206843:
snprintf(name_buffer, sizeof(name_buffer), "AL%d", rounded_size);
break;
@@ -192,9 +189,9 @@ static int parse_gasmixes(device_data_t *devdata, struct dive *dive, dc_parser_t
snprintf(name_buffer, sizeof(name_buffer), "%d cuft", rounded_size);
break;
}
- dive->cylinder[i].type.description = copy_string(name_buffer);
- dive->cylinder[i].type.size.mliter = lrint(cuft_to_l(rounded_size) * 1000 /
- mbar_to_atm(dive->cylinder[i].type.workingpressure.mbar));
+ cyl.type.description = copy_string(name_buffer);
+ cyl.type.size.mliter = lrint(cuft_to_l(rounded_size) * 1000 /
+ mbar_to_atm(cyl.type.workingpressure.mbar));
}
}
if (tank.gasmix != i) { // we don't handle this, yet
@@ -213,22 +210,24 @@ static int parse_gasmixes(device_data_t *devdata, struct dive *dive, dc_parser_t
// rest of the code treats this as if they were valid values
if (!IS_FP_SAME(tank.beginpressure, 0.0)) {
if (!IS_FP_SAME(tank.endpressure, 0.0)) {
- dive->cylinder[i].start.mbar = lrint(tank.beginpressure * 1000);
- dive->cylinder[i].end.mbar = lrint(tank.endpressure * 1000);
+ cyl.start.mbar = lrint(tank.beginpressure * 1000);
+ cyl.end.mbar = lrint(tank.endpressure * 1000);
} else if (same_string(devdata->vendor, "Uwatec")) {
- dive->cylinder[i].start.mbar = lrint(tank.beginpressure * 1000 + 30000);
- dive->cylinder[i].end.mbar = 30000;
+ cyl.start.mbar = lrint(tank.beginpressure * 1000 + 30000);
+ cyl.end.mbar = 30000;
}
}
}
if (no_volume) {
/* for the first tank, if there is no tanksize available from the
* dive computer, fill in the default tank information (if set) */
- fill_default_cylinder(dive, i);
+ fill_default_cylinder(dive, &cyl);
}
/* whatever happens, make sure there is a name for the cylinder */
- if (empty_string(dive->cylinder[i].type.description))
- dive->cylinder[i].type.description = strdup(translate("gettextFromC", "unknown"));
+ if (empty_string(cyl.type.description))
+ cyl.type.description = strdup(translate("gettextFromC", "unknown"));
+
+ add_to_cylinder_table(&dive->cylinders, dive->cylinders.nr, cyl);
}
return DC_STATUS_SUCCESS;
}
@@ -294,7 +293,8 @@ static void handle_event(struct divecomputer *dc, struct sample *sample, dc_samp
static void handle_gasmix(struct divecomputer *dc, struct sample *sample, int idx)
{
- if (idx < 0 || idx >= MAX_CYLINDERS)
+ /* TODO: Verify that index is not higher than the number of cylinders */
+ if (idx < 0)
return;
add_event(dc, sample->time.seconds, SAMPLE_EVENT_GASCHANGE2, idx+1, 0, "gaschange");
current_gas_index = idx;
diff --git a/core/liquivision.c b/core/liquivision.c
index 1e430bcf1..1ea2b814a 100644
--- a/core/liquivision.c
+++ b/core/liquivision.c
@@ -148,8 +148,11 @@ static void parse_dives(int log_version, const unsigned char *buf, unsigned int
dc = &dive->dc;
/* Just the main cylinder until we can handle the buddy cylinder porperly */
- for (i = 0; i < 1; i++)
- fill_default_cylinder(dive, i);
+ for (i = 0; i < 1; i++) {
+ cylinder_t cyl = { 0 };
+ fill_default_cylinder(dive, &cyl);
+ add_to_cylinder_table(&dive->cylinders, i, cyl);
+ }
// Model 0=Xen, 1,2=Xeo, 4=Lynx, other=Liquivision
model = *(buf + ptr);
diff --git a/core/load-git.c b/core/load-git.c
index 2fdb6197b..8cefc5b9f 100644
--- a/core/load-git.c
+++ b/core/load-git.c
@@ -34,7 +34,6 @@ struct git_parser_state {
dive_trip_t *active_trip;
struct picture *active_pic;
struct dive_site *active_site;
- int cylinder_index, weightsystem_index;
int o2pressure_sensor;
};
@@ -391,23 +390,21 @@ static void parse_cylinder_keyvalue(void *_cylinder, const char *key, const char
static void parse_dive_cylinder(char *line, struct membuffer *str, struct git_parser_state *state)
{
- cylinder_t *cylinder = state->active_dive->cylinder + state->cylinder_index;
+ cylinder_t cylinder = { 0 };
- if (state->cylinder_index >= MAX_CYLINDERS)
- return;
-
- cylinder->type.description = get_utf8(str);
+ cylinder.type.description = get_utf8(str);
for (;;) {
char c;
while (isspace(c = *line))
line++;
if (!c)
break;
- line = parse_keyvalue_entry(parse_cylinder_keyvalue, cylinder, line);
+ line = parse_keyvalue_entry(parse_cylinder_keyvalue, &cylinder, line);
}
- if (cylinder->cylinder_use == OXYGEN)
- state->o2pressure_sensor = state->cylinder_index;
- state->cylinder_index++;
+ if (cylinder.cylinder_use == OXYGEN)
+ state->o2pressure_sensor = state->active_dive->cylinders.nr;
+
+ add_to_cylinder_table(&state->active_dive->cylinders, state->active_dive->cylinders.nr, cylinder);
}
static void parse_weightsystem_keyvalue(void *_ws, const char *key, const char *value)
@@ -1493,7 +1490,6 @@ static int parse_dive_entry(struct git_parser_state *state, const git_tree_entry
return report_error("Unable to read dive file");
if (*suffix)
dive->number = atoi(suffix + 1);
- state->cylinder_index = 0;
clear_weightsystem_table(&state->active_dive->weightsystems);
state->o2pressure_sensor = 1;
for_each_line(blob, dive_parser, state);
diff --git a/core/parse-xml.c b/core/parse-xml.c
index 8a7c4e2b9..02363bde6 100644
--- a/core/parse-xml.c
+++ b/core/parse-xml.c
@@ -225,7 +225,7 @@ static void cylinder_use(char *buffer, enum cylinderuse *cyl_use, struct parser_
int use = cylinderuse_from_text(buffer);
*cyl_use = use;
if (use == OXYGEN)
- state->o2pressure_sensor = state->cur_cylinder_index;
+ state->o2pressure_sensor = state->cur_dive->cylinders.nr - 1;
}
}
@@ -408,8 +408,7 @@ static void gasmix(char *buffer, fraction_t *fraction, struct parser_state *stat
/* libdivecomputer does negative percentages. */
if (*buffer == '-')
return;
- if (state->cur_cylinder_index < MAX_CYLINDERS)
- percent(buffer, fraction);
+ percent(buffer, fraction);
}
static void gasmix_nitrogen(char *buffer, struct gasmix *gasmix)
@@ -700,10 +699,12 @@ static void try_to_match_autogroup(const char *name, char *buf)
void add_gas_switch_event(struct dive *dive, struct divecomputer *dc, int seconds, int idx)
{
/* sanity check so we don't crash */
- if (idx < 0 || idx >= MAX_CYLINDERS)
+ if (idx < 0 || idx >= dive->cylinders.nr) {
+ report_error("Unknown cylinder index: %d", idx);
return;
+ }
/* The gas switch event format is insane for historical reasons */
- struct gasmix mix = dive->cylinder[idx].gasmix;
+ struct gasmix mix = dive->cylinders.cylinders[idx].gasmix;
int o2 = get_o2(mix);
int he = get_he(mix);
struct event *ev;
@@ -1000,16 +1001,35 @@ static void divinglog_place(char *place, struct dive *d, struct parser_state *st
static int divinglog_dive_match(struct dive *dive, const char *name, char *buf, struct parser_state *state)
{
+ /* For cylinder related fields, we might have to create a cylinder first. */
+ cylinder_t cyl = { 0 };
+ if (MATCH("tanktype", utf8_string, &cyl.type.description)) {
+ cylinder_t *cyl0 = get_or_create_cylinder(dive, 0);
+ free((void *)cyl0->type.description);
+ cyl0->type.description = cyl.type.description;
+ return 1;
+ }
+ if (MATCH("tanksize", cylindersize, &cyl.type.size)) {
+ get_or_create_cylinder(dive, 0)->type.size = cyl.type.size;
+ return 1;
+ }
+ if (MATCH_STATE("presw", pressure, &cyl.type.workingpressure)) {
+ get_or_create_cylinder(dive, 0)->type.workingpressure = cyl.type.workingpressure;
+ return 1;
+ }
+ if (MATCH_STATE("press", pressure, &cyl.start)) {
+ get_or_create_cylinder(dive, 0)->start = cyl.start;
+ return 1;
+ }
+ if (MATCH_STATE("prese", pressure, &cyl.end)) {
+ get_or_create_cylinder(dive, 0)->end = cyl.end;
+ return 1;
+ }
return MATCH_STATE("divedate", divedate, &dive->when) ||
MATCH_STATE("entrytime", divetime, &dive->when) ||
MATCH("divetime", duration, &dive->dc.duration) ||
MATCH_STATE("depth", depth, &dive->dc.maxdepth) ||
MATCH_STATE("depthavg", depth, &dive->dc.meandepth) ||
- MATCH("tanktype", utf8_string, &dive->cylinder[0].type.description) ||
- MATCH("tanksize", cylindersize, &dive->cylinder[0].type.size) ||
- MATCH_STATE("presw", pressure, &dive->cylinder[0].type.workingpressure) ||
- MATCH_STATE("press", pressure, &dive->cylinder[0].start) ||
- MATCH_STATE("prese", pressure, &dive->cylinder[0].end) ||
MATCH("comments", utf8_string, &dive->notes) ||
MATCH("names.buddy", utf8_string, &dive->buddy) ||
MATCH("name.country", utf8_string, &state->country) ||
@@ -1222,6 +1242,8 @@ static void gps_picture_location(char *buffer, struct picture *pic)
static void try_to_fill_dive(struct dive *dive, const char *name, char *buf, struct parser_state *state)
{
char *hash = NULL;
+ cylinder_t *cyl = dive->cylinders.nr > 0 ? &dive->cylinders.cylinders[dive->cylinders.nr - 1] : NULL;
+ pressure_t p;
start_match("dive", name, buf);
switch (state->import_source) {
@@ -1270,10 +1292,14 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf, str
free(hash);
return;
}
- if (MATCH_STATE("cylinderstartpressure", pressure, &dive->cylinder[0].start))
+ if (MATCH_STATE("cylinderstartpressure", pressure, &p)) {
+ get_or_create_cylinder(dive, 0)->start = p;
return;
- if (MATCH_STATE("cylinderendpressure", pressure, &dive->cylinder[0].end))
+ }
+ if (MATCH_STATE("cylinderendpressure", pressure, &p)) {
+ get_or_create_cylinder(dive, 0)->end = p;
return;
+ }
if (MATCH_STATE("gps", gps_in_dive, dive))
return;
if (MATCH_STATE("Place", gps_in_dive, dive))
@@ -1316,28 +1342,28 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf, str
return;
if (MATCH_STATE("weight", weight, &dive->weightsystems.weightsystems[dive->weightsystems.nr - 1].weight))
return;
- if (state->cur_cylinder_index < MAX_CYLINDERS) {
- if (MATCH("size.cylinder", cylindersize, &dive->cylinder[state->cur_cylinder_index].type.size))
+ if (cyl) {
+ if (MATCH("size.cylinder", cylindersize, &cyl->type.size))
return;
- if (MATCH_STATE("workpressure.cylinder", pressure, &dive->cylinder[state->cur_cylinder_index].type.workingpressure))
+ if (MATCH_STATE("workpressure.cylinder", pressure, &cyl->type.workingpressure))
return;
- if (MATCH("description.cylinder", utf8_string, &dive->cylinder[state->cur_cylinder_index].type.description))
+ if (MATCH("description.cylinder", utf8_string, &cyl->type.description))
return;
- if (MATCH_STATE("start.cylinder", pressure, &dive->cylinder[state->cur_cylinder_index].start))
+ if (MATCH_STATE("start.cylinder", pressure, &cyl->start))
return;
- if (MATCH_STATE("end.cylinder", pressure, &dive->cylinder[state->cur_cylinder_index].end))
+ if (MATCH_STATE("end.cylinder", pressure, &cyl->end))
return;
- if (MATCH_STATE("use.cylinder", cylinder_use, &dive->cylinder[state->cur_cylinder_index].cylinder_use))
+ if (MATCH_STATE("use.cylinder", cylinder_use, &cyl->cylinder_use))
return;
- if (MATCH_STATE("depth.cylinder", depth, &dive->cylinder[state->cur_cylinder_index].depth))
+ if (MATCH_STATE("depth.cylinder", depth, &cyl->depth))
return;
- if (MATCH_STATE("o2", gasmix, &dive->cylinder[state->cur_cylinder_index].gasmix.o2))
+ if (MATCH_STATE("o2", gasmix, &cyl->gasmix.o2))
return;
- if (MATCH_STATE("o2percent", gasmix, &dive->cylinder[state->cur_cylinder_index].gasmix.o2))
+ if (MATCH_STATE("o2percent", gasmix, &cyl->gasmix.o2))
return;
- if (MATCH("n2", gasmix_nitrogen, &dive->cylinder[state->cur_cylinder_index].gasmix))
+ if (MATCH("n2", gasmix_nitrogen, &cyl->gasmix))
return;
- if (MATCH_STATE("he", gasmix, &dive->cylinder[state->cur_cylinder_index].gasmix.he))
+ if (MATCH_STATE("he", gasmix, &cyl->gasmix.he))
return;
}
if (MATCH_STATE("air.divetemperature", temperature, &dive->airtemp))
@@ -1710,6 +1736,7 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size, struct dive_table *tabl
struct battery_status battery_start = {0, 0, 0, 0};
struct battery_status battery_end = {0, 0, 0, 0};
uint16_t o2_sensor_calibration_values[4] = {0};
+ cylinder_t *cyl;
struct parser_state state;
init_parser_state(&state);
@@ -1765,8 +1792,9 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size, struct dive_table *tabl
state.cur_dc->surface_pressure.mbar = ((ptr[25] << 8) + ptr[24]) / 10;
// Declare initial mix as first cylinder
- state.cur_dive->cylinder[0].gasmix.o2.permille = ptr[26] * 10;
- state.cur_dive->cylinder[0].gasmix.he.permille = ptr[27] * 10;
+ cyl = get_or_create_cylinder(state.cur_dive, 0);
+ cyl->gasmix.o2.permille = ptr[26] * 10;
+ cyl->gasmix.he.permille = ptr[27] * 10;
/* Done with parsing what we know about the dive header */
ptr += 32;
@@ -1874,18 +1902,20 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size, struct dive_table *tabl
state.cur_event.value = ptr[7] << 8 ^ ptr[6];
found = false;
- for (i = 0; i < state.cur_cylinder_index; ++i) {
- if (state.cur_dive->cylinder[i].gasmix.o2.permille == ptr[6] * 10 && state.cur_dive->cylinder[i].gasmix.he.permille == ptr[7] * 10) {
+ for (i = 0; i < state.cur_dive->cylinders.nr; ++i) {
+ const cylinder_t *cyl = &state.cur_dive->cylinders.cylinders[i];
+ if (cyl->gasmix.o2.permille == ptr[6] * 10 && cyl->gasmix.he.permille == ptr[7] * 10) {
found = true;
break;
}
}
if (!found) {
cylinder_start(&state);
- state.cur_dive->cylinder[state.cur_cylinder_index].gasmix.o2.permille = ptr[6] * 10;
- state.cur_dive->cylinder[state.cur_cylinder_index].gasmix.he.permille = ptr[7] * 10;
+ cylinder_t *cyl = &state.cur_dive->cylinders.cylinders[state.cur_dive->cylinders.nr - 1];
+ cyl->gasmix.o2.permille = ptr[6] * 10;
+ cyl->gasmix.he.permille = ptr[7] * 10;
cylinder_end(&state);
- state.cur_event.gas.index = state.cur_cylinder_index;
+ state.cur_event.gas.index = state.cur_dive->cylinders.nr - 1;
} else {
state.cur_event.gas.index = i;
}
diff --git a/core/parse.c b/core/parse.c
index 8344d3552..dd8c612e8 100644
--- a/core/parse.c
+++ b/core/parse.c
@@ -257,7 +257,6 @@ void dive_end(struct parser_state *state)
state->cur_dc = NULL;
state->cur_location.lat.udeg = 0;
state->cur_location.lon.udeg = 0;
- state->cur_cylinder_index = 0;
}
void trip_start(struct parser_state *state)
@@ -290,11 +289,11 @@ void picture_end(struct parser_state *state)
void cylinder_start(struct parser_state *state)
{
+ add_empty_cylinder(&state->cur_dive->cylinders);
}
void cylinder_end(struct parser_state *state)
{
- state->cur_cylinder_index++;
}
void ws_start(struct parser_state *state)
diff --git a/core/parse.h b/core/parse.h
index 79ba57098..a36ca0e61 100644
--- a/core/parse.h
+++ b/core/parse.h
@@ -54,7 +54,6 @@ struct parser_state {
bool in_settings;
bool in_userid;
struct tm cur_tm;
- int cur_cylinder_index;
int lastcylinderindex, next_o2_sensor;
int o2pressure_sensor;
int sample_rate;
diff --git a/core/planner.c b/core/planner.c
index d488413c8..4a480640d 100644
--- a/core/planner.c
+++ b/core/planner.c
@@ -89,7 +89,7 @@ int get_cylinderid_at_time(struct dive *dive, struct divecomputer *dc, duration_
int get_gasidx(struct dive *dive, struct gasmix mix)
{
- return find_best_gasmix_match(mix, dive->cylinder);
+ return find_best_gasmix_match(mix, &dive->cylinders);
}
static void interpolate_transition(struct deco_state *ds, struct dive *dive, duration_t t0, duration_t t1, depth_t d0, depth_t d1, struct gasmix gasmix, o2pressure_t po2, enum divemode_t divemode)
@@ -177,10 +177,9 @@ static int tissue_at_end(struct deco_state *ds, struct dive *dive, struct deco_s
/* if a default cylinder is set, use that */
-void fill_default_cylinder(struct dive *dive, int idx)
+void fill_default_cylinder(const struct dive *dive, cylinder_t *cyl)
{
const char *cyl_name = prefs.default_cylinder;
- cylinder_t *cyl = &dive->cylinder[idx];
struct tank_info_t *ti = tank_info;
pressure_t pO2 = {.mbar = 1600};
@@ -270,7 +269,7 @@ static void create_dive_from_plan(struct diveplan *diveplan, struct dive *dive,
/* Create first sample at time = 0, not based on dp because
* there is no real dp for time = 0, set first cylinder to 0
* O2 setpoint for this sample will be filled later from next dp */
- cyl = &dive->cylinder[0];
+ cyl = get_or_create_cylinder(dive, 0);
sample = prepare_sample(dc);
sample->sac.mliter = prefs.bottomsac;
if (track_gas && cyl->type.workingpressure.mbar)
@@ -304,7 +303,7 @@ static void create_dive_from_plan(struct diveplan *diveplan, struct dive *dive,
if (dp->cylinderid != lastcylid) {
/* need to insert a first sample for the new gas */
add_gas_switch_event(dive, dc, lasttime + 1, dp->cylinderid);
- cyl = &dive->cylinder[dp->cylinderid];
+ cyl = get_or_create_cylinder(dive, dp->cylinderid);
sample = prepare_sample(dc);
sample[-1].setpoint.mbar = po2;
sample->time.seconds = lasttime + 1;
@@ -410,7 +409,7 @@ static struct gaschanges *analyze_gaslist(struct diveplan *diveplan, struct dive
int nr = 0;
struct gaschanges *gaschanges = NULL;
struct divedatapoint *dp = diveplan->dp;
- int best_depth = dive->cylinder[*asc_cylinder].depth.mm;
+ int best_depth = dive->cylinders.cylinders[*asc_cylinder].depth.mm;
bool total_time_zero = true;
while (dp) {
if (dp->time == 0 && total_time_zero) {
@@ -445,7 +444,7 @@ static struct gaschanges *analyze_gaslist(struct diveplan *diveplan, struct dive
for (nr = 0; nr < *gaschangenr; nr++) {
int idx = gaschanges[nr].gasidx;
printf("gaschange nr %d: @ %5.2lfm gasidx %d (%s)\n", nr, gaschanges[nr].depth / 1000.0,
- idx, gasname(dive->cylinder[idx].gasmix));
+ idx, gasname(dive->cylinders.cylinders[idx].gasmix));
}
#endif
return gaschanges;
@@ -528,7 +527,7 @@ int ascent_velocity(int depth, int avg_depth, int bottom_time)
static void track_ascent_gas(int depth, struct dive *dive, int cylinder_id, int avg_depth, int bottom_time, bool safety_stop, enum divemode_t divemode)
{
- cylinder_t *cylinder = &dive->cylinder[cylinder_id];
+ cylinder_t *cylinder = &dive->cylinders.cylinders[cylinder_id];
while (depth > 0) {
int deltad = ascent_velocity(depth, avg_depth, bottom_time) * TIMESTEP;
if (deltad > depth)
@@ -596,7 +595,10 @@ static bool trial_ascent(struct deco_state *ds, int wait_time, int trial_depth,
*/
static bool enough_gas(const struct dive *dive, int current_cylinder)
{
- const cylinder_t *cyl = &dive->cylinder[current_cylinder];
+ cylinder_t *cyl;
+ if (current_cylinder < 0 || current_cylinder >= dive->cylinders.nr)
+ return false;
+ cyl = &dive->cylinders.cylinders[current_cylinder];
if (!cyl->start.mbar)
return true;
@@ -730,7 +732,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
const struct event *ev = NULL;
divemode = UNDEF_COMP_TYPE;
divemode = get_current_divemode(&dive->dc, bottom_time, &ev, &divemode);
- gas = dive->cylinder[current_cylinder].gasmix;
+ gas = dive->cylinders.cylinders[current_cylinder].gasmix;
po2 = sample->setpoint.mbar;
depth = dive->dc.sample[dive->dc.samples - 1].depth.mm;
@@ -785,11 +787,11 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
// How long can we stay at the current depth and still directly ascent to the surface?
do {
add_segment(ds, depth_to_bar(depth, dive),
- dive->cylinder[current_cylinder].gasmix,
+ dive->cylinders.cylinders[current_cylinder].gasmix,
timestep, po2, divemode, prefs.bottomsac);
- update_cylinder_pressure(dive, depth, depth, timestep, prefs.bottomsac, &dive->cylinder[current_cylinder], false, divemode);
+ update_cylinder_pressure(dive, depth, depth, timestep, prefs.bottomsac, &dive->cylinders.cylinders[current_cylinder], false, divemode);
clock += timestep;
- } while (trial_ascent(ds, 0, depth, 0, avg_depth, bottom_time, dive->cylinder[current_cylinder].gasmix,
+ } while (trial_ascent(ds, 0, depth, 0, avg_depth, bottom_time, dive->cylinders.cylinders[current_cylinder].gasmix,
po2, diveplan->surface_pressure / 1000.0, dive, divemode) &&
enough_gas(dive, current_cylinder) && clock < 6 * 3600);
@@ -797,7 +799,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
// In the best of all worlds, we would roll back also the last add_segment in terms of caching deco state, but
// let's ignore that since for the eventual ascent in recreational mode, nobody looks at the ceiling anymore,
// so we don't really have to compute the deco state.
- update_cylinder_pressure(dive, depth, depth, -timestep, prefs.bottomsac, &dive->cylinder[current_cylinder], false, divemode);
+ update_cylinder_pressure(dive, depth, depth, -timestep, prefs.bottomsac, &dive->cylinders.cylinders[current_cylinder], false, divemode);
clock -= timestep;
plan_add_segment(diveplan, clock - previous_point_time, depth, current_cylinder, po2, true, divemode);
previous_point_time = clock;
@@ -835,7 +837,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
if (best_first_ascend_cylinder != current_cylinder) {
current_cylinder = best_first_ascend_cylinder;
- gas = dive->cylinder[current_cylinder].gasmix;
+ gas = dive->cylinders.cylinders[current_cylinder].gasmix;
#if DEBUG_PLAN & 16
printf("switch to gas %d (%d/%d) @ %5.2lfm\n", best_first_ascend_cylinder,
@@ -849,7 +851,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
divemode = OC;
po2 = 0;
add_segment(ds, depth_to_bar(depth, dive),
- dive->cylinder[current_cylinder].gasmix,
+ dive->cylinders.cylinders[current_cylinder].gasmix,
prefs.min_switch_duration, po2, divemode, prefs.bottomsac);
plan_add_segment(diveplan, prefs.min_switch_duration, depth, current_cylinder, po2, false, divemode);
clock += prefs.min_switch_duration;
@@ -891,7 +893,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
last_ascend_rate = ascent_velocity(depth, avg_depth, bottom_time);
/* Always prefer the best_first_ascend_cylinder if it has the right gasmix.
* Otherwise take first cylinder from list with rightgasmix */
- if (same_gasmix(gas, dive->cylinder[best_first_ascend_cylinder].gasmix))
+ if (same_gasmix(gas, dive->cylinders.cylinders[best_first_ascend_cylinder].gasmix))
current_cylinder = best_first_ascend_cylinder;
else
current_cylinder = get_gasidx(dive, gas);
@@ -916,7 +918,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
deltad = depth - stoplevels[stopidx];
add_segment(ds, depth_to_bar(depth, dive),
- dive->cylinder[current_cylinder].gasmix,
+ dive->cylinders.cylinders[current_cylinder].gasmix,
TIMESTEP, po2, divemode, prefs.decosac);
last_segment_min_switch = false;
clock += TIMESTEP;
@@ -941,21 +943,21 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
if (current_cylinder != gaschanges[gi].gasidx) {
if (!prefs.switch_at_req_stop ||
!trial_ascent(ds, 0, depth, stoplevels[stopidx - 1], avg_depth, bottom_time,
- dive->cylinder[current_cylinder].gasmix, po2, diveplan->surface_pressure / 1000.0, dive, divemode) || get_o2(dive->cylinder[current_cylinder].gasmix) < 160) {
+ dive->cylinders.cylinders[current_cylinder].gasmix, po2, diveplan->surface_pressure / 1000.0, dive, divemode) || get_o2(dive->cylinders.cylinders[current_cylinder].gasmix) < 160) {
if (is_final_plan)
plan_add_segment(diveplan, clock - previous_point_time, depth, current_cylinder, po2, false, divemode);
stopping = true;
previous_point_time = clock;
current_cylinder = gaschanges[gi].gasidx;
- gas = dive->cylinder[current_cylinder].gasmix;
+ gas = dive->cylinders.cylinders[current_cylinder].gasmix;
#if DEBUG_PLAN & 16
printf("switch to gas %d (%d/%d) @ %5.2lfm\n", gaschanges[gi].gasidx,
(get_o2(&gas) + 5) / 10, (get_he(&gas) + 5) / 10, gaschanges[gi].depth / 1000.0);
#endif
/* Stop for the minimum duration to switch gas unless we switch to o2 */
- if (!last_segment_min_switch && get_o2(dive->cylinder[current_cylinder].gasmix) != 1000) {
+ if (!last_segment_min_switch && get_o2(dive->cylinders.cylinders[current_cylinder].gasmix) != 1000) {
add_segment(ds, depth_to_bar(depth, dive),
- dive->cylinder[current_cylinder].gasmix,
+ dive->cylinders.cylinders[current_cylinder].gasmix,
prefs.min_switch_duration, po2, divemode, prefs.decosac);
clock += prefs.min_switch_duration;
last_segment_min_switch = true;
@@ -975,7 +977,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
while (1) {
/* Check if ascending to next stop is clear, go back and wait if we hit the ceiling on the way */
if (trial_ascent(ds, 0, depth, stoplevels[stopidx], avg_depth, bottom_time,
- dive->cylinder[current_cylinder].gasmix, po2, diveplan->surface_pressure / 1000.0, dive, divemode)) {
+ dive->cylinders.cylinders[current_cylinder].gasmix, po2, diveplan->surface_pressure / 1000.0, dive, divemode)) {
decostoptable[decostopcounter].depth = depth;
decostoptable[decostopcounter].time = 0;
decostopcounter++;
@@ -1001,15 +1003,15 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
*/
if (pendinggaschange) {
current_cylinder = gaschanges[gi + 1].gasidx;
- gas = dive->cylinder[current_cylinder].gasmix;
+ gas = dive->cylinders.cylinders[current_cylinder].gasmix;
#if DEBUG_PLAN & 16
printf("switch to gas %d (%d/%d) @ %5.2lfm\n", gaschanges[gi + 1].gasidx,
(get_o2(&gas) + 5) / 10, (get_he(&gas) + 5) / 10, gaschanges[gi + 1].depth / 1000.0);
#endif
/* Stop for the minimum duration to switch gas unless we switch to o2 */
- if (!last_segment_min_switch && get_o2(dive->cylinder[current_cylinder].gasmix) != 1000) {
+ if (!last_segment_min_switch && get_o2(dive->cylinders.cylinders[current_cylinder].gasmix) != 1000) {
add_segment(ds, depth_to_bar(depth, dive),
- dive->cylinder[current_cylinder].gasmix,
+ dive->cylinders.cylinders[current_cylinder].gasmix,
prefs.min_switch_duration, po2, divemode, prefs.decosac);
clock += prefs.min_switch_duration;
last_segment_min_switch = true;
@@ -1018,7 +1020,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
}
int new_clock = wait_until(ds, dive, clock, clock, laststoptime * 2 + 1, timestep, depth, stoplevels[stopidx], avg_depth,
- bottom_time, dive->cylinder[current_cylinder].gasmix, po2, diveplan->surface_pressure / 1000.0, divemode);
+ bottom_time, dive->cylinders.cylinders[current_cylinder].gasmix, po2, diveplan->surface_pressure / 1000.0, divemode);
laststoptime = new_clock - clock;
/* Finish infinite deco */
if (laststoptime >= 48 * 3600 && depth >= 6000) {
@@ -1033,12 +1035,12 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
* backgas. This could be customized if there were demand.
*/
if (break_cylinder == -1) {
- if (get_o2(dive->cylinder[best_first_ascend_cylinder].gasmix) <= 320)
+ if (get_o2(dive->cylinders.cylinders[best_first_ascend_cylinder].gasmix) <= 320)
break_cylinder = best_first_ascend_cylinder;
else
break_cylinder = 0;
}
- if (get_o2(dive->cylinder[current_cylinder].gasmix) == 1000) {
+ if (get_o2(dive->cylinders.cylinders[current_cylinder].gasmix) == 1000) {
if (laststoptime >= 12 * 60) {
laststoptime = 12 * 60;
new_clock = clock + laststoptime;
@@ -1049,7 +1051,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
plan_add_segment(diveplan, laststoptime, depth, current_cylinder, po2, false, divemode);
previous_point_time = clock + laststoptime;
current_cylinder = break_cylinder;
- gas = dive->cylinder[current_cylinder].gasmix;
+ gas = dive->cylinders.cylinders[current_cylinder].gasmix;
}
} else if (o2break_next) {
if (laststoptime >= 6 * 60) {
@@ -1061,11 +1063,11 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
plan_add_segment(diveplan, laststoptime, depth, current_cylinder, po2, false, divemode);
previous_point_time = clock + laststoptime;
current_cylinder = breakfrom_cylinder;
- gas = dive->cylinder[current_cylinder].gasmix;
+ gas = dive->cylinders.cylinders[current_cylinder].gasmix;
}
}
}
- add_segment(ds, depth_to_bar(depth, dive), dive->cylinder[stop_cylinder].gasmix,
+ add_segment(ds, depth_to_bar(depth, dive), dive->cylinders.cylinders[stop_cylinder].gasmix,
laststoptime, po2, divemode, prefs.decosac);
last_segment_min_switch = false;
decostoptable[decostopcounter].depth = depth;
@@ -1099,14 +1101,12 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
}
if (prefs.surface_segment != 0) {
- for (int i = 0; i < MAX_CYLINDERS; i++)
- if (cylinder_nodata(&dive->cylinder[i])) {
- // Switch to an empty air cylinder for breathing air at the surface
- // If no empty cylinder is found, keep using last deco gas
- current_cylinder = i;
- dive->cylinder[i].cylinder_use = NOT_USED;
- break;
- }
+ // Switch to an empty air cylinder for breathing air at the surface
+ // If no empty cylinder is found, keep using last deco gas
+ cylinder_t cyl = { 0 };
+ cyl.cylinder_use = NOT_USED;
+ add_to_cylinder_table(&dive->cylinders, dive->cylinders.nr, cyl);
+ current_cylinder = dive->cylinders.nr - 1;
plan_add_segment(diveplan, prefs.surface_segment, 0, current_cylinder, 0, false, OC);
}
create_dive_from_plan(diveplan, dive, is_planner);
diff --git a/core/plannernotes.c b/core/plannernotes.c
index 0bfdbe7d5..dd909108a 100644
--- a/core/plannernotes.c
+++ b/core/plannernotes.c
@@ -190,13 +190,13 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
nextdp = dp->next;
if (dp->time == 0)
continue;
- gasmix = dive->cylinder[dp->cylinderid].gasmix;
+ gasmix = dive->cylinders.cylinders[dp->cylinderid].gasmix;
depthvalue = get_depth_units(dp->depth.mm, &decimals, &depth_unit);
/* analyze the dive points ahead */
while (nextdp && nextdp->time == 0)
nextdp = nextdp->next;
if (nextdp)
- newgasmix = dive->cylinder[nextdp->cylinderid].gasmix;
+ newgasmix = dive->cylinders.cylinders[nextdp->cylinderid].gasmix;
gaschange_after = (nextdp && (gasmix_distance(gasmix, newgasmix)));
gaschange_before = (gasmix_distance(lastprintgasmix, gasmix));
rebreatherchange_after = (nextdp && (dp->setpoint != nextdp->setpoint || dp->divemode != nextdp->divemode));
@@ -461,16 +461,14 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
free(temp);
/* Print gas consumption: This loop covers all cylinders */
- for (int gasidx = 0; gasidx < MAX_CYLINDERS; gasidx++) {
+ for (int gasidx = 0; gasidx < dive->cylinders.nr; gasidx++) {
double volume, pressure, deco_volume, deco_pressure, mingas_volume, mingas_pressure, mingas_d_pressure, mingas_depth;
const char *unit, *pressure_unit, *depth_unit;
char warning[1000] = "";
char mingas[1000] = "";
- cylinder_t *cyl = &dive->cylinder[gasidx];
+ cylinder_t *cyl = &dive->cylinders.cylinders[gasidx];
if (cyl->cylinder_use == NOT_USED)
continue;
- if (cylinder_none(cyl))
- break;
volume = get_volume_units(cyl->gas_used.mliter, NULL, &unit);
deco_volume = get_volume_units(cyl->deco_gas_used.mliter, NULL, &unit);
@@ -583,7 +581,7 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
while (dp) {
if (dp->time != 0) {
struct gas_pressures pressures;
- struct gasmix gasmix = dive->cylinder[dp->cylinderid].gasmix;
+ struct gasmix gasmix = dive->cylinders.cylinders[dp->cylinderid].gasmix;
current_divemode = get_current_divemode(&dive->dc, dp->time, &evd, &current_divemode);
amb = depth_to_atm(dp->depth.mm, dive);
diff --git a/core/profile.c b/core/profile.c
index 8fd669989..4d35155b2 100644
--- a/core/profile.c
+++ b/core/profile.c
@@ -189,7 +189,7 @@ static int get_local_sac(struct plot_info *pi, int idx1, int idx2, struct dive *
depth = (entry1->depth + entry2->depth) / 2;
atm = depth_to_atm(depth, dive);
- cyl = dive->cylinder + index;
+ cyl = dive->cylinders.cylinders + index;
airuse = gas_volume(cyl, a) - gas_volume(cyl, b);
@@ -334,7 +334,7 @@ int get_cylinder_index(const struct dive *dive, const struct event *ev)
fprintf(stderr, "Still looking up cylinder based on gas mix in get_cylinder_index()!\n");
mix = get_gasmix_from_event(dive, ev);
- best = find_best_gasmix_match(mix, dive->cylinder);
+ best = find_best_gasmix_match(mix, &dive->cylinders);
return best < 0 ? 0 : best;
}
@@ -413,8 +413,8 @@ static void calculate_max_limits_new(struct dive *dive, struct divecomputer *giv
int cyl;
/* Get the per-cylinder maximum pressure if they are manual */
- for (cyl = 0; cyl < MAX_CYLINDERS; cyl++) {
- int mbar = dive->cylinder[cyl].start.mbar;
+ for (cyl = 0; cyl < dive->cylinders.nr; cyl++) {
+ int mbar = dive->cylinders.cylinders[cyl].start.mbar;
if (mbar > maxpressure)
maxpressure = mbar;
if (mbar < minpressure)
@@ -534,7 +534,8 @@ static void populate_plot_entries(struct dive *dive, struct divecomputer *dc, st
nr = dc->samples + 6 + maxtime / 10 + count_events(dc);
plot_data = calloc(nr, sizeof(struct plot_data));
pi->entry = plot_data;
- pi->pressures = calloc(nr * MAX_CYLINDERS, sizeof(struct plot_pressure_data));
+ pi->nr_cylinders = dive->cylinders.nr;
+ pi->pressures = calloc(nr * (size_t)pi->nr_cylinders, sizeof(struct plot_pressure_data));
if (!plot_data)
return;
pi->nr = nr;
@@ -666,7 +667,7 @@ static int sac_between(struct dive *dive, struct plot_info *pi, int first, int l
/* Get airuse for the set of cylinders over the range */
airuse = 0;
- for (i = 0; i < MAX_CYLINDERS; i++) {
+ for (i = 0; i < pi->nr_cylinders; i++) {
pressure_t a, b;
cylinder_t *cyl;
int cyluse;
@@ -676,7 +677,7 @@ static int sac_between(struct dive *dive, struct plot_info *pi, int first, int l
a.mbar = get_plot_pressure(pi, first, i);
b.mbar = get_plot_pressure(pi, last, i);
- cyl = dive->cylinder + i;
+ cyl = dive->cylinders.cylinders + i;
cyluse = gas_volume(cyl, a) - gas_volume(cyl, b);
if (cyluse > 0)
airuse += cyluse;
@@ -708,7 +709,7 @@ static bool all_pressures(struct plot_info *pi, int idx, const bool gases[])
{
int i;
- for (i = 0; i < MAX_CYLINDERS; i++) {
+ for (i = 0; i < pi->nr_cylinders; i++) {
if (gases[i] && !get_plot_pressure(pi, idx, i))
return false;
}
@@ -722,7 +723,7 @@ static bool filter_pressures(struct plot_info *pi, int idx, const bool gases_in[
int i;
bool has_pressure = false;
- for (i = 0; i < MAX_CYLINDERS; i++) {
+ for (i = 0; i < pi->nr_cylinders; i++) {
gases_out[i] = gases_in[i] && get_plot_pressure(pi, idx, i);
has_pressure |= gases_out[i];
}
@@ -798,8 +799,8 @@ static void matching_gases(struct dive *dive, struct gasmix gasmix, bool gases[]
{
int i;
- for (i = 0; i < MAX_CYLINDERS; i++)
- gases[i] = same_gasmix(gasmix, dive->cylinder[i].gasmix);
+ for (i = 0; i < dive->cylinders.nr; i++)
+ gases[i] = same_gasmix(gasmix, dive->cylinders.cylinders[i].gasmix);
}
static void calculate_sac(struct dive *dive, struct divecomputer *dc, struct plot_info *pi)
@@ -808,12 +809,11 @@ static void calculate_sac(struct dive *dive, struct divecomputer *dc, struct plo
const struct event *ev = NULL;
bool *gases, *gases_scratch;
- gases = malloc(MAX_CYLINDERS * sizeof(*gases));
- memset(gases, 0, MAX_CYLINDERS * sizeof(*gases));
+ gases = calloc(pi->nr_cylinders, sizeof(*gases));
/* This might be premature optimization, but let's allocate the gas array for
* the fill_sac function only once an not once per sample */
- gases_scratch = malloc(MAX_CYLINDERS * sizeof(*gases));
+ gases_scratch = malloc(pi->nr_cylinders * sizeof(*gases));
for (int i = 0; i < pi->nr; i++) {
struct plot_data *entry = pi->entry + i;
@@ -855,12 +855,12 @@ static void setup_gas_sensor_pressure(const struct dive *dive, const struct dive
{
int prev, i;
const struct event *ev;
- int *seen = malloc(MAX_CYLINDERS * sizeof(*seen));
- int *first = malloc(MAX_CYLINDERS * sizeof(*first));
- int *last = malloc(MAX_CYLINDERS * sizeof(*last));
+ int *seen = malloc(pi->nr_cylinders * sizeof(*seen));
+ int *first = malloc(pi->nr_cylinders * sizeof(*first));
+ int *last = malloc(pi->nr_cylinders * sizeof(*last));
const struct divecomputer *secondary;
- for (i = 0; i < MAX_CYLINDERS; i++) {
+ for (i = 0; i < pi->nr_cylinders; i++) {
seen[i] = 0;
first[i] = 0;
last[i] = INT_MAX;
@@ -889,8 +889,8 @@ static void setup_gas_sensor_pressure(const struct dive *dive, const struct dive
// Fill in "seen[]" array - mark cylinders we're not interested
// in as negative.
- for (i = 0; i < MAX_CYLINDERS; i++) {
- const cylinder_t *cyl = dive->cylinder + i;
+ for (i = 0; i < pi->nr_cylinders; i++) {
+ const cylinder_t *cyl = dive->cylinders.cylinders + i;
int start = cyl->start.mbar;
int end = cyl->end.mbar;
@@ -918,10 +918,9 @@ static void setup_gas_sensor_pressure(const struct dive *dive, const struct dive
}
}
-
- for (i = 0; i < MAX_CYLINDERS; i++) {
+ for (i = 0; i < pi->nr_cylinders; i++) {
if (seen[i] >= 0) {
- const cylinder_t *cyl = dive->cylinder + i;
+ const cylinder_t *cyl = dive->cylinders.cylinders + i;
add_plot_pressure(pi, first[i], i, cyl->start);
add_plot_pressure(pi, last[i], i, cyl->end);
@@ -1398,7 +1397,7 @@ void create_plot_info_new(struct dive *dive, struct divecomputer *dc, struct plo
check_setpoint_events(dive, dc, pi); /* Populate setpoints */
setup_gas_sensor_pressure(dive, dc, pi); /* Try to populate our gas pressure knowledge */
if (!fast) {
- for (int cyl = 0; cyl < MAX_CYLINDERS; cyl++)
+ for (int cyl = 0; cyl < pi->nr_cylinders; cyl++)
populate_pressure_information(dive, dc, pi, cyl);
}
fill_o2_values(dive, dc, pi); /* .. and insert the O2 sensor data having 0 values. */
@@ -1439,11 +1438,11 @@ static void plot_string(struct plot_info *pi, int idx, struct membuffer *b)
depthvalue = get_depth_units(entry->depth, NULL, &depth_unit);
put_format_loc(b, translate("gettextFromC", "@: %d:%02d\nD: %.1f%s\n"), FRACTION(entry->sec, 60), depthvalue, depth_unit);
- for (cyl = 0; cyl < MAX_CYLINDERS; cyl++) {
+ for (cyl = 0; cyl < pi->nr_cylinders; cyl++) {
int mbar = get_plot_pressure(pi, idx, cyl);
if (!mbar)
continue;
- struct gasmix mix = displayed_dive.cylinder[cyl].gasmix;
+ struct gasmix mix = displayed_dive.cylinders.cylinders[cyl].gasmix;
pressurevalue = get_pressure_units(mbar, &pressure_unit);
put_format_loc(b, translate("gettextFromC", "P: %d%s (%s)\n"), pressurevalue, pressure_unit, gasname(mix));
}
@@ -1707,7 +1706,7 @@ void compare_samples(struct plot_info *pi, int idx1, int idx2, char *buf, int bu
pressurevalue = get_pressure_units(bar_used, &pressure_unit);
memcpy(buf2, buf, bufsize);
snprintf_loc(buf, bufsize, translate("gettextFromC", "%s ΔP:%d%s"), buf2, pressurevalue, pressure_unit);
- cylinder_t *cyl = displayed_dive.cylinder + 0;
+ cylinder_t *cyl = displayed_dive.cylinders.cylinders + 0;
/* if we didn't cross a tank change and know the cylidner size as well, show SAC rate */
if (!crossed_tankchange && cyl->type.size.mliter) {
double volume_value;
diff --git a/core/qthelper.cpp b/core/qthelper.cpp
index 700854ebc..b8afd8267 100644
--- a/core/qthelper.cpp
+++ b/core/qthelper.cpp
@@ -389,9 +389,9 @@ QVector<QPair<QString, int>> selectedDivesGasUsed()
if (!d->selected)
continue;
volume_t *diveGases = get_gas_used(d);
- for (j = 0; j < MAX_CYLINDERS; j++) {
+ for (j = 0; j < d->cylinders.nr; j++) {
if (diveGases[j].mliter) {
- QString gasName = gasname(d->cylinder[j].gasmix);
+ QString gasName = gasname(d->cylinders.cylinders[j].gasmix);
gasUsed[gasName] += diveGases[j].mliter;
}
}
@@ -1186,7 +1186,7 @@ QString get_gas_string(struct gasmix gas)
QString get_divepoint_gas_string(struct dive *d, const divedatapoint &p)
{
int idx = p.cylinderid;
- return get_gas_string(d->cylinder[idx].gasmix);
+ return get_gas_string(d->cylinders.cylinders[idx].gasmix);
}
QString get_taglist_string(struct tag_entry *tag_list)
diff --git a/core/save-git.c b/core/save-git.c
index ae299af24..662891153 100644
--- a/core/save-git.c
+++ b/core/save-git.c
@@ -138,7 +138,7 @@ static void save_cylinder_info(struct membuffer *b, struct dive *dive)
nr = nr_cylinders(dive);
for (i = 0; i < nr; i++) {
- cylinder_t *cylinder = dive->cylinder + i;
+ cylinder_t *cylinder = dive->cylinders.cylinders + i;
int volume = cylinder->type.size.mliter;
const char *description = cylinder->type.description;
int use = cylinder->cylinder_use;
diff --git a/core/save-html.c b/core/save-html.c
index 09d7152d4..380f2fa8e 100644
--- a/core/save-html.c
+++ b/core/save-html.c
@@ -132,7 +132,7 @@ static void put_cylinder_HTML(struct membuffer *b, struct dive *dive)
put_string(b, separator);
for (i = 0; i < nr; i++) {
- cylinder_t *cylinder = dive->cylinder + i;
+ cylinder_t *cylinder = dive->cylinders.cylinders + i;
put_format(b, "%s{", separator);
separator = ", ";
write_attribute(b, "Type", cylinder->type.description, ", ");
diff --git a/core/save-profiledata.c b/core/save-profiledata.c
index 4f7440708..bc5a8e3a5 100644
--- a/core/save-profiledata.c
+++ b/core/save-profiledata.c
@@ -37,7 +37,7 @@ static void put_pd(struct membuffer *b, const struct plot_info *pi, int idx)
put_int(b, entry->in_deco);
put_int(b, entry->sec);
- for (int c = 0; c < MAX_CYLINDERS; c++) {
+ for (int c = 0; c < pi->nr_cylinders; c++) {
put_int(b, get_plot_sensor_pressure(pi, idx, c));
put_int(b, get_plot_interpolated_pressure(pi, idx, c));
}
@@ -103,11 +103,11 @@ static void put_pd(struct membuffer *b, const struct plot_info *pi, int idx)
put_int(b, entry->icd_warning ? 1 : 0);
}
-static void put_headers(struct membuffer *b)
+static void put_headers(struct membuffer *b, int nr_cylinders)
{
put_csv_string(b, "in_deco");
put_csv_string(b, "sec");
- for (int c = 0; c < MAX_CYLINDERS; c++) {
+ for (int c = 0; c < nr_cylinders; c++) {
put_format(b, "\"pressure_%d_cylinder\", ", c);
put_format(b, "\"pressure_%d_interpolated\", ", c);
}
@@ -203,7 +203,7 @@ static void save_profiles_buffer(struct membuffer *b, bool select_only)
if (select_only && !dive->selected)
continue;
create_plot_info_new(dive, &dive->dc, &pi, false, planner_deco_state);
- put_headers(b);
+ put_headers(b, pi.nr_cylinders);
put_format(b, "\n");
for (int i = 0; i < pi.nr; i++) {
diff --git a/core/save-xml.c b/core/save-xml.c
index 356ee36a7..a7bf6b23e 100644
--- a/core/save-xml.c
+++ b/core/save-xml.c
@@ -179,7 +179,7 @@ static void save_cylinder_info(struct membuffer *b, struct dive *dive)
nr = nr_cylinders(dive);
for (i = 0; i < nr; i++) {
- cylinder_t *cylinder = dive->cylinder + i;
+ cylinder_t *cylinder = dive->cylinders.cylinders + i;
int volume = cylinder->type.size.mliter;
const char *description = cylinder->type.description;
int use = cylinder->cylinder_use;
diff --git a/core/statistics.c b/core/statistics.c
index d5ef58955..fa7985c90 100644
--- a/core/statistics.c
+++ b/core/statistics.c
@@ -330,13 +330,15 @@ bool has_gaschange_event(const struct dive *dive, const struct divecomputer *dc,
bool is_cylinder_used(const struct dive *dive, int idx)
{
const struct divecomputer *dc;
- if (cylinder_none(&dive->cylinder[idx]))
+ cylinder_t *cyl;
+ if (idx < 0 || idx >= dive->cylinders.nr)
return false;
- if ((dive->cylinder[idx].start.mbar - dive->cylinder[idx].end.mbar) > SOME_GAS)
+ cyl = &dive->cylinders.cylinders[idx];
+ if ((cyl->start.mbar - cyl->end.mbar) > SOME_GAS)
return true;
- if ((dive->cylinder[idx].sample_start.mbar - dive->cylinder[idx].sample_end.mbar) > SOME_GAS)
+ if ((cyl->sample_start.mbar - cyl->sample_end.mbar) > SOME_GAS)
return true;
for_each_dc(dive, dc) {
@@ -349,7 +351,7 @@ bool is_cylinder_used(const struct dive *dive, int idx)
bool is_cylinder_prot(const struct dive *dive, int idx)
{
const struct divecomputer *dc;
- if (cylinder_none(&dive->cylinder[idx]))
+ if (idx < 0 || idx >= dive->cylinders.nr)
return false;
for_each_dc(dive, dc) {
@@ -359,15 +361,15 @@ bool is_cylinder_prot(const struct dive *dive, int idx)
return false;
}
-/* Returns a dynamically allocated array with MAX_CYLINDERS entries that
- * has to be freed by the caller */
+/* Returns a dynamically allocated array with dive->cylinders.nr entries,
+ * which has to be freed by the caller */
volume_t *get_gas_used(struct dive *dive)
{
int idx;
- volume_t *gases = malloc(MAX_CYLINDERS * sizeof(volume_t));
- for (idx = 0; idx < MAX_CYLINDERS; idx++) {
- cylinder_t *cyl = &dive->cylinder[idx];
+ volume_t *gases = malloc(dive->cylinders.nr * sizeof(volume_t));
+ for (idx = 0; idx < dive->cylinders.nr; idx++) {
+ cylinder_t *cyl = &dive->cylinders.cylinders[idx];
pressure_t start, end;
start = cyl->start.mbar ? cyl->start : cyl->sample_start;
@@ -403,10 +405,10 @@ void selected_dives_gas_parts(volume_t *o2_tot, volume_t *he_tot)
if (!d->selected)
continue;
volume_t *diveGases = get_gas_used(d);
- for (j = 0; j < MAX_CYLINDERS; j++) {
+ for (j = 0; j < d->cylinders.nr; j++) {
if (diveGases[j].mliter) {
volume_t o2 = {}, he = {};
- get_gas_parts(d->cylinder[j].gasmix, diveGases[j], O2_IN_AIR, &o2, &he);
+ get_gas_parts(d->cylinders.cylinders[j].gasmix, diveGases[j], O2_IN_AIR, &o2, &he);
o2_tot->mliter += o2.mliter;
he_tot->mliter += he.mliter;
}
diff --git a/core/subsurface-qt/DiveObjectHelper.cpp b/core/subsurface-qt/DiveObjectHelper.cpp
index 5146a6ea1..1deffdd4e 100644
--- a/core/subsurface-qt/DiveObjectHelper.cpp
+++ b/core/subsurface-qt/DiveObjectHelper.cpp
@@ -32,7 +32,7 @@ static QString getFormattedWeight(const struct dive *dive, unsigned int idx)
static QString getFormattedCylinder(const struct dive *dive, unsigned int idx)
{
- const cylinder_t *cyl = &dive->cylinder[idx];
+ const cylinder_t *cyl = &dive->cylinders.cylinders[idx];
const char *desc = cyl->type.description;
if (!desc && idx > 0)
return QString();
@@ -46,7 +46,7 @@ static QString getFormattedCylinder(const struct dive *dive, unsigned int idx)
static QString getPressures(const struct dive *dive, int i, enum returnPressureSelector ret)
{
- const cylinder_t *cyl = &dive->cylinder[i];
+ const cylinder_t *cyl = &dive->cylinders.cylinders[i];
QString fmt;
if (ret == START_PRESSURE) {
if (cyl->start.mbar)
@@ -101,13 +101,13 @@ static QString formatGas(const dive *d)
* from the get_gas_string function or this is correct?
*/
QString gas, gases;
- for (int i = 0; i < MAX_CYLINDERS; i++) {
+ for (int i = 0; i < d->cylinders.nr; i++) {
if (!is_cylinder_used(d, i))
continue;
- gas = d->cylinder[i].type.description;
+ gas = d->cylinders.cylinders[i].type.description;
if (!gas.isEmpty())
gas += QChar(' ');
- gas += gasname(d->cylinder[i].gasmix);
+ gas += gasname(d->cylinders.cylinders[i].gasmix);
// if has a description and if such gas is not already present
if (!gas.isEmpty() && gases.indexOf(gas) == -1) {
if (!gases.isEmpty())
@@ -155,10 +155,8 @@ static QStringList formatWeights(const dive *d)
QStringList formatCylinders(const dive *d)
{
QStringList cylinders;
- for (int i = 0; i < MAX_CYLINDERS; i++) {
+ for (int i = 0; i < d->cylinders.nr; i++) {
QString cyl = getFormattedCylinder(d, i);
- if (cyl.isEmpty())
- continue;
cylinders << cyl;
}
return cylinders;
@@ -167,10 +165,10 @@ QStringList formatCylinders(const dive *d)
static QVector<CylinderObjectHelper> makeCylinderObjects(const dive *d)
{
QVector<CylinderObjectHelper> res;
- for (int i = 0; i < MAX_CYLINDERS; i++) {
+ for (int i = 0; i < d->cylinders.nr; i++) {
//Don't add blank cylinders, only those that have been defined.
- if (d->cylinder[i].type.description)
- res.append(CylinderObjectHelper(&d->cylinder[i])); // no emplace for QVector. :(
+ if (d->cylinders.cylinders[i].type.description)
+ res.append(CylinderObjectHelper(&d->cylinders.cylinders[i])); // no emplace for QVector. :(
}
return res;
}
@@ -178,9 +176,9 @@ static QVector<CylinderObjectHelper> makeCylinderObjects(const dive *d)
QStringList formatGetCylinder(const dive *d)
{
QStringList getCylinder;
- for (int i = 0; i < MAX_CYLINDERS; i++) {
+ for (int i = 0; i < d->cylinders.nr; i++) {
if (is_cylinder_used(d, i))
- getCylinder << d->cylinder[i].type.description;
+ getCylinder << d->cylinders.cylinders[i].type.description;
}
return getCylinder;
}
@@ -188,7 +186,7 @@ QStringList formatGetCylinder(const dive *d)
QStringList getStartPressure(const dive *d)
{
QStringList startPressure;
- for (int i = 0; i < MAX_CYLINDERS; i++) {
+ for (int i = 0; i < d->cylinders.nr; i++) {
if (is_cylinder_used(d, i))
startPressure << getPressures(d, i, START_PRESSURE);
}
@@ -198,7 +196,7 @@ QStringList getStartPressure(const dive *d)
QStringList getEndPressure(const dive *d)
{
QStringList endPressure;
- for (int i = 0; i < MAX_CYLINDERS; i++) {
+ for (int i = 0; i < d->cylinders.nr; i++) {
if (is_cylinder_used(d, i))
endPressure << getPressures(d, i, END_PRESSURE);
}
@@ -208,9 +206,9 @@ QStringList getEndPressure(const dive *d)
QStringList getFirstGas(const dive *d)
{
QStringList gas;
- for (int i = 0; i < MAX_CYLINDERS; i++) {
+ for (int i = 0; i < d->cylinders.nr; i++) {
if (is_cylinder_used(d, i))
- gas << get_gas_string(d->cylinder[i].gasmix);
+ gas << get_gas_string(d->cylinders.cylinders[i].gasmix);
}
return gas;
}
@@ -221,10 +219,8 @@ QStringList getFullCylinderList()
int i = 0;
struct dive *d;
for_each_dive (i, d) {
- for (int j = 0; j < MAX_CYLINDERS; j++) {
- QString cyl = d->cylinder[j].type.description;
- if (cyl.isEmpty())
- continue;
+ for (int j = 0; j < d->cylinders.nr; j++) {
+ QString cyl = d->cylinders.cylinders[j].type.description;
cylinders << cyl;
}
}
diff --git a/core/uemis.c b/core/uemis.c
index 88f402400..7272e2897 100644
--- a/core/uemis.c
+++ b/core/uemis.c
@@ -336,17 +336,18 @@ void uemis_parse_divelog_binary(char *base64, void *datap)
* we store the incorrect working pressure to get the SAC calculations "close"
* but the user will have to correct this manually
*/
- dive->cylinder[i].type.size.mliter = lrintf(volume);
- dive->cylinder[i].type.workingpressure.mbar = 202600;
- dive->cylinder[i].gasmix.o2.permille = *(uint8_t *)(data + 120 + 25 * (gasoffset + i)) * 10;
- dive->cylinder[i].gasmix.he.permille = 0;
+ cylinder_t *cyl = get_or_create_cylinder(dive, i);
+ cyl->type.size.mliter = lrintf(volume);
+ cyl->type.workingpressure.mbar = 202600;
+ cyl->gasmix.o2.permille = *(uint8_t *)(data + 120 + 25 * (gasoffset + i)) * 10;
+ cyl->gasmix.he.permille = 0;
}
/* first byte of divelog data is at offset 0x123 */
i = 0x123;
u_sample = (uemis_sample_t *)(data + i);
while ((i <= datalen) && (data[i] != 0 || data[i + 1] != 0)) {
if (u_sample->active_tank != active) {
- if (u_sample->active_tank >= MAX_CYLINDERS) {
+ if (u_sample->active_tank >= dive->cylinders.nr) {
fprintf(stderr, "got invalid sensor #%d was #%d\n", u_sample->active_tank, active);
} else {
active = u_sample->active_tank;