diff options
author | Petr Machata <pmachata@redhat.com> | 2012-11-23 18:35:05 +0100 |
---|---|---|
committer | Petr Machata <pmachata@redhat.com> | 2013-03-08 22:52:31 +0100 |
commit | c28410e3f4bb4d40e48d58440800fbb080b2e3d6 (patch) | |
tree | f3d33aa4b4255b0903928ad5e10aa144b0ac897e | |
parent | 3e86576623d16c5032af4d50108eb878166fb686 (diff) | |
download | ltrace-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.c | 2 | ||||
-rw-r--r-- | vect.c | 33 | ||||
-rw-r--r-- | vect.h | 28 |
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; } @@ -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); } @@ -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 |