| /* |
| * This file is part of ltrace. |
| * Copyright (C) 2011,2012,2013 Petr Machata, Red Hat Inc. |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License as |
| * published by the Free Software Foundation; either version 2 of the |
| * License, or (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA |
| * 02110-1301 USA |
| */ |
| |
| #ifndef VECT_H |
| #define VECT_H |
| |
| #include <stddef.h> |
| #include <assert.h> |
| |
| #include "callback.h" |
| |
| /* Vector is an array that can grow as needed to accommodate the data |
| * that it needs to hold. ELT_SIZE is also used as an elementary |
| * sanity check, because the array itself is not typed. */ |
| |
| struct vect |
| { |
| void *data; |
| size_t size; /* In elements. */ |
| size_t allocated; /* In elements. */ |
| size_t elt_size; /* In bytes. */ |
| }; |
| |
| /* Initialize VEC, which will hold elements of size ELT_SIZE. */ |
| void vect_init(struct vect *vec, size_t elt_size); |
| |
| /* Initialize VECP, which will hold elements of type ELT_TYPE. */ |
| #define VECT_INIT(VECP, ELT_TYPE) \ |
| (vect_init(VECP, sizeof(ELT_TYPE))) |
| |
| /* Initialize TARGET by copying over contents of vector SOURCE. If |
| * CLONE is non-NULL, it's evoked on each element, and should clone |
| * SRC into TGT. It should return 0 on success or negative value on |
| * failure. DATA is passed to CLONE verbatim. This function returns |
| * 0 on success or negative value on failure. In case of failure, if |
| * DTOR is non-NULL, it is invoked on all hitherto created elements |
| * with the same DATA. If one of CLONE, DTOR is non-NULL, then both |
| * have to be. */ |
| int vect_clone(struct vect *target, const struct vect *source, |
| int (*clone)(void *tgt, const void *src, void *data), |
| void (*dtor)(void *elt, void *data), |
| void *data); |
| |
| /* Destroy VEC, which holds elements of type ELT_TYPE, using DTOR. */ |
| #define VECT_CLONE(TGT_VEC, SRC_VEC, ELT_TYPE, CLONE, DTOR, DATA) \ |
| /* xxx GCC-ism necessary to get in the safety latches. */ \ |
| ({ \ |
| const struct vect *_source_vec = (SRC_VEC); \ |
| assert(_source_vec->elt_size == sizeof(ELT_TYPE)); \ |
| /* Check that callbacks are typed properly. */ \ |
| void (*_dtor_callback)(ELT_TYPE *, void *) = DTOR; \ |
| int (*_clone_callback)(ELT_TYPE *, const ELT_TYPE *, \ |
| void *) = CLONE; \ |
| vect_clone((TGT_VEC), _source_vec, \ |
| (int (*)(void *, const void *, \ |
| void *))_clone_callback, \ |
| (void (*)(void *, void *))_dtor_callback, \ |
| DATA); \ |
| }) |
| |
| /* Return number of elements in VEC. */ |
| size_t vect_size(const struct vect *vec); |
| |
| /* Emptiness predicate. */ |
| int vect_empty(const struct vect *vec); |
| |
| /* Accessor. Fetch ELT_NUM-th argument of type ELT_TYPE from the |
| * vector referenced by VECP. */ |
| #define VECT_ELEMENT(VECP, ELT_TYPE, ELT_NUM) \ |
| (assert((VECP)->elt_size == sizeof(ELT_TYPE)), \ |
| assert((ELT_NUM) < (VECP)->size), \ |
| ((ELT_TYPE *)(VECP)->data) + (ELT_NUM)) |
| |
| #define VECT_BACK(VECP, ELT_TYPE) \ |
| VECT_ELEMENT(VECP, ELT_TYPE, (VECP)->size - 1) |
| |
| /* Copy element referenced by ELTP to the end of VEC. The object |
| * referenced by ELTP is now owned by VECT. Returns 0 if the |
| * operation was successful, or negative value on error. */ |
| int vect_pushback(struct vect *vec, void *eltp); |
| |
| /* 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 |
| * holds elements of the right size. */ |
| #define VECT_PUSHBACK(VECP, ELTP) \ |
| (assert((VECP)->elt_size == sizeof(*(ELTP))), \ |
| vect_pushback((VECP), (ELTP))) |
| |
| /* Make sure that VEC can hold at least COUNT elements. Return 0 on |
| * success, negative value on failure. */ |
| int vect_reserve(struct vect *vec, size_t count); |
| |
| /* Make sure that VEC can accommodate COUNT additional elements. */ |
| int vect_reserve_additional(struct vect *vec, size_t count); |
| |
| /* Destroy VEC. If DTOR is non-NULL, then it's called on each element |
| * of the vector. DATA is passed to DTOR verbatim. The memory |
| * pointed-to by VEC is not freed. */ |
| void vect_destroy(struct vect *vec, |
| void (*dtor)(void *emt, void *data), void *data); |
| |
| /* Destroy VEC, which holds elements of type ELT_TYPE, using DTOR. */ |
| #define VECT_DESTROY(VECP, ELT_TYPE, DTOR, DATA) \ |
| do { \ |
| assert((VECP)->elt_size == sizeof(ELT_TYPE)); \ |
| /* Check that DTOR is typed properly. */ \ |
| void (*_dtor_callback)(ELT_TYPE *, void *) = DTOR; \ |
| vect_destroy((VECP), (void (*)(void *, void *))_dtor_callback, \ |
| DATA); \ |
| } while (0) |
| |
| /* Iterate through vector VEC. See callback.h for notes on iteration |
| * interfaces. */ |
| void *vect_each(struct vect *vec, void *start_after, |
| enum callback_status (*cb)(void *, void *), void *data); |
| |
| #define VECT_EACH(VECP, ELT_TYPE, START_AFTER, CB, DATA) \ |
| /* xxx GCC-ism necessary to get in the safety latches. */ \ |
| ({ \ |
| assert((VECP)->elt_size == sizeof(ELT_TYPE)); \ |
| /* Check that CB is typed properly. */ \ |
| enum callback_status (*_cb)(ELT_TYPE *, void *) = CB; \ |
| ELT_TYPE *_start_after = (START_AFTER); \ |
| (ELT_TYPE *)vect_each((VECP), _start_after, \ |
| (enum callback_status \ |
| (*)(void *, void *))_cb, \ |
| DATA); \ |
| }) |
| |
| /* Iterate through vector VEC. See callback.h for notes on iteration |
| * interfaces. */ |
| const void *vect_each_cst(const struct vect *vec, const void *start_after, |
| enum callback_status (*cb)(const void *, void *), |
| void *data); |
| |
| #define VECT_EACH_CST(VECP, ELT_TYPE, START_AFTER, CB, DATA) \ |
| /* xxx GCC-ism necessary to get in the safety latches. */ \ |
| ({ \ |
| assert((VECP)->elt_size == sizeof(ELT_TYPE)); \ |
| /* Check that CB is typed properly. */ \ |
| enum callback_status (*_cb)(const ELT_TYPE *, void *) = CB; \ |
| const ELT_TYPE *start_after = (START_AFTER); \ |
| (const ELT_TYPE *)vect_each_cst((VECP), start_after, \ |
| (enum callback_status \ |
| (*)(const void *, \ |
| void *))_cb, \ |
| DATA); \ |
| }) |
| |
| /* Call qsort on elements of VECT, with COMPAR as a comparison |
| * function. */ |
| void vect_qsort(struct vect *vec, int (*compar)(const void *, const void *)); |
| |
| #define VECT_QSORT(VECP, ELT_TYPE, COMPAR) \ |
| do { \ |
| assert((VECP)->elt_size == sizeof(ELT_TYPE)); \ |
| /* Check that CB is typed properly. */ \ |
| int (*_compar)(const ELT_TYPE *, const ELT_TYPE *) = COMPAR; \ |
| vect_qsort((VECP), \ |
| (int (*)(const void *, const void *))_compar); \ |
| } while (0) |
| |
| |
| /* A dtor which calls 'free' on elements of a vector. */ |
| void vect_dtor_string(char **key, void *data); |
| |
| #endif /* VECT_H */ |