aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Machata <pmachata@redhat.com>2012-11-23 18:35:05 +0100
committerPetr Machata <pmachata@redhat.com>2013-03-08 22:52:31 +0100
commitc28410e3f4bb4d40e48d58440800fbb080b2e3d6 (patch)
treef3d33aa4b4255b0903928ad5e10aa144b0ac897e
parent3e86576623d16c5032af4d50108eb878166fb686 (diff)
downloadltrace-c28410e3f4bb4d40e48d58440800fbb080b2e3d6.tar.gz
Add vect_erase, VECT_ERASE. VECT_POPBACK needs a dtor
vect_popback and VECT_POPBACK are now defined in terms of vect_erase and VECT_ERASE, respectively.
-rw-r--r--lens_default.c2
-rw-r--r--vect.c33
-rw-r--r--vect.h28
3 files changed, 52 insertions, 11 deletions
diff --git a/lens_default.c b/lens_default.c
index 9f60dae..26ba22e 100644
--- a/lens_default.c
+++ b/lens_default.c
@@ -321,7 +321,7 @@ format_pointer(FILE *stream, struct value *value, struct value_dict *arguments)
value_destroy(&element);
done:
- vect_popback(&pointers);
+ VECT_POPBACK(&pointers, struct value *, NULL, NULL);
return o;
}
diff --git a/vect.c b/vect.c
index 3a29118..a97977c 100644
--- a/vect.c
+++ b/vect.c
@@ -129,9 +129,30 @@ vect_pushback(struct vect *vec, void *eltp)
}
void
-vect_popback(struct vect *vec)
+vect_erase(struct vect *vec, size_t start, size_t end,
+ void (*dtor)(void *emt, void *data), void *data)
{
- vec->size--;
+ assert(start < vect_size(vec) || start == 0);
+ assert(end <= vect_size(vec));
+
+ /* First, destroy the elements that are to be erased. */
+ if (dtor != NULL) {
+ size_t i;
+ for (i = start; i < end; ++i)
+ dtor(slot(vec, i), data);
+ }
+
+ /* Now move the tail forward and adjust size. */
+ memmove(slot(vec, start), slot(vec, end), vec->size - end);
+ vec->size -= end - start;
+}
+
+void
+vect_popback(struct vect *vec,
+ void (*dtor)(void *emt, void *data), void *data)
+{
+ assert(vect_size(vec) > 0);
+ vect_erase(vec, vect_size(vec)-1, vect_size(vec), dtor, data);
}
void
@@ -140,12 +161,8 @@ vect_destroy(struct vect *vec, void (*dtor)(void *emt, void *data), void *data)
if (vec == NULL)
return;
- if (dtor != NULL) {
- size_t i;
- size_t sz = vect_size(vec);
- for (i = 0; i < sz; ++i)
- dtor(slot(vec, i), data);
- }
+ vect_erase(vec, 0, vect_size(vec), dtor, data);
+ assert(vect_size(vec) == 0);
free(vec->data);
}
diff --git a/vect.h b/vect.h
index 0f9951d..1c444c1 100644
--- a/vect.h
+++ b/vect.h
@@ -96,8 +96,32 @@ int vect_empty(const struct vect *vec);
* operation was successful, or negative value on error. */
int vect_pushback(struct vect *vec, void *eltp);
-/* Drop last element of VECP. */
-void vect_popback(struct vect *vec);
+/* Drop last element of VECP. This is like calling
+ * vect_erase(VEC, vect_size(VEC)-1, vect_size(VEC), DTOR, DATA); */
+void vect_popback(struct vect *vec,
+ void (*dtor)(void *emt, void *data), void *data);
+
+#define VECT_POPBACK(VECP, ELT_TYPE, DTOR, DATA) \
+ do \
+ VECT_ERASE((VECP), ELT_TYPE, \
+ vect_size(VECP) - 1, vect_size(VECP), \
+ DTOR, DATA); \
+ while (0)
+
+/* Drop elements START (inclusive) to END (non-inclusive) of VECP. If
+ * DTOR is non-NULL, it is called on each of the removed elements.
+ * DATA is passed verbatim to DTOR. */
+void vect_erase(struct vect *vec, size_t start, size_t end,
+ void (*dtor)(void *emt, void *data), void *data);
+
+#define VECT_ERASE(VECP, ELT_TYPE, START, END, DTOR, DATA) \
+ do { \
+ assert((VECP)->elt_size == sizeof(ELT_TYPE)); \
+ /* Check that DTOR is typed properly. */ \
+ void (*_dtor_callback)(ELT_TYPE *, void *) = DTOR; \
+ vect_erase((VECP), (START), (END), \
+ (void (*)(void *, void *))_dtor_callback, DATA); \
+ } while (0)
/* Copy element referenced by ELTP to the end of VEC. See
* vect_pushback for details. In addition, make a check whether VECP