vect.h revision 08423ca4f329d9fc13458d23fede961da493d329
1/* 2 * This file is part of ltrace. 3 * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc. 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation; either version 2 of the 8 * License, or (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 18 * 02110-1301 USA 19 */ 20 21#ifndef VECT_H 22#define VECT_H 23 24#include <stddef.h> 25#include <assert.h> 26 27#include "callback.h" 28 29/* Vector is an array that can grow as needed to accommodate the data 30 * that it needs to hold. ELT_SIZE is also used as an elementary 31 * sanity check, because the array itself is not typed. */ 32 33struct vect 34{ 35 void *data; 36 size_t size; /* In elements. */ 37 size_t allocated; /* In elements. */ 38 size_t elt_size; /* In bytes. */ 39}; 40 41/* Initialize VEC, which will hold elements of size ELT_SIZE. */ 42void vect_init(struct vect *vec, size_t elt_size); 43 44/* Initialize VECP, which will hold elements of type ELT_TYPE. */ 45#define VECT_INIT(VECP, ELT_TYPE) \ 46 (vect_init(VECP, sizeof(ELT_TYPE))) 47 48/* Initialize TARGET by copying over contents of vector SOURCE. If 49 * CLONE is non-NULL, it's evoked on each element, and should clone 50 * SRC into TGT. It should return 0 on success or negative value on 51 * failure. DATA is passed to CLONE verbatim. This function returns 52 * 0 on success or negative value on failure. In case of failure, if 53 * DTOR is non-NULL, it is invoked on all hitherto created elements 54 * with the same DATA. If one of CLONE, DTOR is non-NULL, then both 55 * have to be. */ 56int vect_clone(struct vect *target, const struct vect *source, 57 int (*clone)(void *tgt, const void *src, void *data), 58 void (*dtor)(void *elt, void *data), 59 void *data); 60 61/* Destroy VEC, which holds elements of type ELT_TYPE, using DTOR. */ 62#define VECT_CLONE(TGT_VEC, SRC_VEC, ELT_TYPE, CLONE, DTOR, DATA) \ 63 /* xxx GCC-ism necessary to get in the safety latches. */ \ 64 ({ \ 65 const struct vect *_source_vec = (SRC_VEC); \ 66 assert(_source_vec->elt_size == sizeof(ELT_TYPE)); \ 67 /* Check that callbacks are typed properly. */ \ 68 void (*_dtor_callback)(ELT_TYPE *, void *) = DTOR; \ 69 int (*_clone_callback)(ELT_TYPE *, const ELT_TYPE *, \ 70 void *) = CLONE; \ 71 vect_clone((TGT_VEC), _source_vec, \ 72 (int (*)(void *, const void *, \ 73 void *))_clone_callback, \ 74 (void (*)(void *, void *))_dtor_callback, \ 75 DATA); \ 76 }) 77 78/* Return number of elements in VEC. */ 79size_t vect_size(const struct vect *vec); 80 81/* Emptiness predicate. */ 82int vect_empty(const struct vect *vec); 83 84/* Accessor. Fetch ELT_NUM-th argument of type ELT_TYPE from the 85 * vector referenced by VECP. */ 86#define VECT_ELEMENT(VECP, ELT_TYPE, ELT_NUM) \ 87 (assert((VECP)->elt_size == sizeof(ELT_TYPE)), \ 88 assert((ELT_NUM) < (VECP)->size), \ 89 ((ELT_TYPE *)(VECP)->data) + (ELT_NUM)) 90 91#define VECT_BACK(VECP, ELT_TYPE) \ 92 VECT_ELEMENT(VECP, ELT_TYPE, (VECP)->size - 1) 93 94/* Copy element referenced by ELTP to the end of VEC. The object 95 * referenced by ELTP is now owned by VECT. Returns 0 if the 96 * operation was successful, or negative value on error. */ 97int vect_pushback(struct vect *vec, void *eltp); 98 99/* Drop last element of VECP. */ 100void vect_popback(struct vect *vec); 101 102/* Copy element referenced by ELTP to the end of VEC. See 103 * vect_pushback for details. In addition, make a check whether VECP 104 * holds elements of the right size. */ 105#define VECT_PUSHBACK(VECP, ELTP) \ 106 (assert((VECP)->elt_size == sizeof(*(ELTP))), \ 107 vect_pushback((VECP), (ELTP))) 108 109/* Make sure that VEC can hold at least COUNT elements. Return 0 on 110 * success, negative value on failure. */ 111int vect_reserve(struct vect *vec, size_t count); 112 113/* Make sure that VEC can accommodate COUNT additional elements. */ 114int vect_reserve_additional(struct vect *vec, size_t count); 115 116/* Destroy VEC. If DTOR is non-NULL, then it's called on each element 117 * of the vector. DATA is passed to DTOR verbatim. The memory 118 * pointed-to by VEC is not freed. */ 119void vect_destroy(struct vect *vec, 120 void (*dtor)(void *emt, void *data), void *data); 121 122/* Destroy VEC, which holds elements of type ELT_TYPE, using DTOR. */ 123#define VECT_DESTROY(VECP, ELT_TYPE, DTOR, DATA) \ 124 do { \ 125 assert((VECP)->elt_size == sizeof(ELT_TYPE)); \ 126 /* Check that DTOR is typed properly. */ \ 127 void (*_dtor_callback)(ELT_TYPE *, void *) = DTOR; \ 128 vect_destroy((VECP), (void (*)(void *, void *))_dtor_callback, \ 129 DATA); \ 130 } while (0) 131 132/* Iterate through vector VEC. See callback.h for notes on iteration 133 * interfaces. */ 134void *vect_each(struct vect *vec, void *start_after, 135 enum callback_status (*cb)(void *, void *), void *data); 136 137#define VECT_EACH(VECP, ELT_TYPE, START_AFTER, CB, DATA) \ 138 /* xxx GCC-ism necessary to get in the safety latches. */ \ 139 ({ \ 140 assert((VECP)->elt_size == sizeof(ELT_TYPE)); \ 141 /* Check that CB is typed properly. */ \ 142 enum callback_status (*_cb)(ELT_TYPE *, void *) = CB; \ 143 ELT_TYPE *start_after = (START_AFTER); \ 144 (ELT_TYPE *)vect_each((VECP), start_after, \ 145 (enum callback_status \ 146 (*)(void *, void *))_cb, \ 147 DATA); \ 148 }) 149 150#endif /* VECT_H */ 151