vect.h revision 49d3d52e19692f92cf2114b053053c549a723b79
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, struct vect *source, 57 int (*clone)(void *tgt, 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 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 *, \ 70 ELT_TYPE *, void *) = CLONE; \ 71 vect_clone((TGT_VEC), _source_vec, \ 72 (int (*)(void *, void *, void *))_clone_callback, \ 73 (void (*)(void *, void *))_dtor_callback, \ 74 DATA); \ 75 }) 76 77/* Return number of elements in VEC. */ 78size_t vect_size(struct vect *vec); 79 80/* Emptiness predicate. */ 81int vect_empty(struct vect *vec); 82 83/* Accessor. Fetch ELT_NUM-th argument of type ELT_TYPE from the 84 * vector referenced by VECP. */ 85#define VECT_ELEMENT(VECP, ELT_TYPE, ELT_NUM) \ 86 (assert((VECP)->elt_size == sizeof(ELT_TYPE)), \ 87 assert((ELT_NUM) < (VECP)->size), \ 88 ((ELT_TYPE *)(VECP)->data) + (ELT_NUM)) 89 90#define VECT_BACK(VECP, ELT_TYPE) \ 91 VECT_ELEMENT(VECP, ELT_TYPE, (VECP)->size) 92 93/* Copy element referenced by ELTP to the end of VEC. The object 94 * referenced by ELTP is now owned by VECT. Returns 0 if the 95 * operation was successful, or negative value on error. */ 96int vect_pushback(struct vect *vec, void *eltp); 97 98/* Copy element referenced by ELTP to the end of VEC. See 99 * vect_pushback for details. In addition, make a check whether VECP 100 * holds elements of the right size. */ 101#define VECT_PUSHBACK(VECP, ELTP) \ 102 (assert((VECP)->elt_size == sizeof(*(ELTP))), \ 103 vect_pushback((VECP), (ELTP))) 104 105/* Make sure that VEC can hold at least COUNT elements. Return 0 on 106 * success, negative value on failure. */ 107int vect_reserve(struct vect *vec, size_t count); 108 109/* Make sure that VEC can accommodate COUNT additional elements. */ 110int vect_reserve_additional(struct vect *vec, size_t count); 111 112/* Destroy VEC. If DTOR is non-NULL, then it's called on each element 113 * of the vector. DATA is passed to DTOR verbatim. The memory 114 * pointed-to by VEC is not freed. */ 115void vect_destroy(struct vect *vec, 116 void (*dtor)(void *emt, void *data), void *data); 117 118/* Destroy VEC, which holds elements of type ELT_TYPE, using DTOR. */ 119#define VECT_DESTROY(VECP, ELT_TYPE, DTOR, DATA) \ 120 do { \ 121 assert((VECP)->elt_size == sizeof(ELT_TYPE)); \ 122 /* Check that DTOR is typed properly. */ \ 123 void (*_dtor_callback)(ELT_TYPE *, void *) = DTOR; \ 124 vect_destroy((VECP), (void (*)(void *, void *))_dtor_callback, \ 125 DATA); \ 126 } while (0) 127 128/* Iterate through vector VEC. See callback.h for notes on iteration 129 * interfaces. */ 130void *vect_each(struct vect *vec, void *start_after, 131 enum callback_status (*cb)(void *, void *), void *data); 132 133#define VECT_EACH(VECP, ELT_TYPE, START_AFTER, CB, DATA) \ 134 /* xxx GCC-ism necessary to get in the safety latches. */ \ 135 ({ \ 136 assert((VECP)->elt_size == sizeof(ELT_TYPE)); \ 137 /* Check that CB is typed properly. */ \ 138 enum callback_status (*_cb)(ELT_TYPE *, void *) = CB; \ 139 ELT_TYPE *start_after = (START_AFTER); \ 140 (ELT_TYPE *)vect_each((VECP), start_after, \ 141 (enum callback_status \ 142 (*)(void *, void *))_cb, \ 143 DATA); \ 144 }) 145 146#endif /* VECT_H */ 147