summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Berthold Stoeger <bstoeger@mail.tuwien.ac.at>2018-10-16 07:41:48 +0200
committerGravatar Dirk Hohndel <dirk@hohndel.org>2018-10-16 06:20:33 -0400
commitc61cf991e01f562cbcbd228c42e057db6690fea8 (patch)
tree708ed38ed96d92c97f8bcd2df0f0d86849c76e7e
parent763c3683e58684f296d6b66835ca6d84e14b3900 (diff)
downloadsubsurface-c61cf991e01f562cbcbd228c42e057db6690fea8.tar.gz
Core: copy and free extra_data of dive computer structure
On dive computer copy, the extra data (a list of key/value pairs) was simply copied as a pointer. This worked because the list was never freed nor modified. Copy and free the list on dive computer copy and free, respectively. This made it necessary to move the STRUCTURE_LIST_* macros up in the dive.c file. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
-rw-r--r--core/dive.c72
1 files changed, 42 insertions, 30 deletions
diff --git a/core/dive.c b/core/dive.c
index 345b59c2c..303288b4e 100644
--- a/core/dive.c
+++ b/core/dive.c
@@ -473,10 +473,42 @@ struct dive *alloc_dive(void)
return dive;
}
+/* Clear everything but the first element;
+ * this works for taglist, picturelist, even dive computers */
+#define STRUCTURED_LIST_FREE(_type, _start, _free) \
+ { \
+ _type *_ptr = _start; \
+ while (_ptr) { \
+ _type *_next = _ptr->next; \
+ _free(_ptr); \
+ _ptr = _next; \
+ } \
+ }
+
+#define STRUCTURED_LIST_COPY(_type, _first, _dest, _cpy) \
+ { \
+ _type *_sptr = _first; \
+ _type **_dptr = &_dest; \
+ while (_sptr) { \
+ *_dptr = malloc(sizeof(_type)); \
+ _cpy(_sptr, *_dptr); \
+ _sptr = _sptr->next; \
+ _dptr = &(*_dptr)->next; \
+ } \
+ *_dptr = 0; \
+ }
+
static void free_dc(struct divecomputer *dc);
static void free_dc_contents(struct divecomputer *dc);
static void free_pic(struct picture *picture);
+/* copy an element in a list of dive computer extra data */
+static void copy_extra_data(struct extra_data *sed, struct extra_data *ded)
+{
+ ded->key = copy_string(sed->key);
+ ded->value = copy_string(sed->value);
+}
+
/* this is very different from the copy_divecomputer later in this file;
* this function actually makes full copies of the content */
static void copy_dc(const struct divecomputer *sdc, struct divecomputer *ddc)
@@ -485,6 +517,7 @@ static void copy_dc(const struct divecomputer *sdc, struct divecomputer *ddc)
ddc->model = copy_string(sdc->model);
copy_samples(sdc, ddc);
copy_events(sdc, ddc);
+ STRUCTURED_LIST_COPY(struct extra_data, sdc->extra_data, ddc->extra_data, copy_extra_data);
}
static void dc_cylinder_renumber(struct dive *dive, struct divecomputer *dc, const int mapping[]);
@@ -495,10 +528,7 @@ static void dc_cylinder_renumber(struct dive *dive, struct divecomputer *dc, con
static void copy_dc_renumber(struct dive *d, const struct divecomputer *sdc, struct divecomputer *ddc, const int cylinders_map[])
{
for (;;) {
- *ddc = *sdc;
- ddc->model = copy_string(sdc->model);
- copy_samples(sdc, ddc);
- copy_events(sdc, ddc);
+ copy_dc(sdc, ddc);
dc_cylinder_renumber(d, ddc, cylinders_map);
if (!sdc->next)
break;
@@ -524,31 +554,6 @@ static void copy_tl(struct tag_entry *st, struct tag_entry *dt)
dt->tag->source = copy_string(st->tag->source);
}
-/* Clear everything but the first element;
- * this works for taglist, picturelist, even dive computers */
-#define STRUCTURED_LIST_FREE(_type, _start, _free) \
- { \
- _type *_ptr = _start; \
- while (_ptr) { \
- _type *_next = _ptr->next; \
- _free(_ptr); \
- _ptr = _next; \
- } \
- }
-
-#define STRUCTURED_LIST_COPY(_type, _first, _dest, _cpy) \
- { \
- _type *_sptr = _first; \
- _type **_dptr = &_dest; \
- while (_sptr) { \
- *_dptr = malloc(sizeof(_type)); \
- _cpy(_sptr, *_dptr); \
- _sptr = _sptr->next; \
- _dptr = &(*_dptr)->next; \
- } \
- *_dptr = 0; \
- }
-
static void free_dive_structures(struct dive *d)
{
if (!d)
@@ -2961,11 +2966,18 @@ void free_events(struct event *ev)
}
}
+static void free_extra_data(struct extra_data *ed)
+{
+ free((void *)ed->key);
+ free((void *)ed->value);
+}
+
static void free_dc_contents(struct divecomputer *dc)
{
free(dc->sample);
free((void *)dc->model);
free_events(dc->events);
+ STRUCTURED_LIST_FREE(struct extra_data, dc->extra_data, free_extra_data);
}
static void free_dc(struct divecomputer *dc)
@@ -3075,11 +3087,11 @@ static const struct divecomputer *find_matching_computer(const struct divecomput
return p;
}
-
static void copy_dive_computer(struct divecomputer *res, const struct divecomputer *a)
{
*res = *a;
res->model = copy_string(a->model);
+ STRUCTURED_LIST_COPY(struct extra_data, a->extra_data, res->extra_data, copy_extra_data);
res->samples = res->alloc_samples = 0;
res->sample = NULL;
res->events = NULL;