vect.h revision a0a6a54a41d828c9a018829033443b0faabefb2f
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 26/* Vector is an array that can grow as needed to accommodate the data 27 * that it needs to hold. ELT_SIZE is also used as an elementary 28 * sanity check, because the array itself is not typed. */ 29 30struct vect 31{ 32 void *data; 33 size_t size; /* In elements. */ 34 size_t allocated; /* In elements. */ 35 size_t elt_size; /* In bytes. */ 36}; 37 38/* Initialize VEC, which will hold elements of size ELT_SIZE. */ 39void vect_init(struct vect *vec, size_t elt_size); 40 41/* Initialize VECP, which will hold elements of type ELT_TYPE. */ 42#define VECT_INIT(VECP, ELT_TYPE) \ 43 (vect_init(VECP, sizeof(ELT_TYPE))) 44 45/* Initialize TARGET by copying over contents of vector SOURCE. If 46 * CLONE is non-NULL, it's evoked on each element, and should clone 47 * SRC into TGT. It should return 0 on success or negative value on 48 * failure. DATA is passed to CLONE verbatim. This function returns 49 * 0 on success or negative value on failure. In case of failure, if 50 * DTOR is non-NULL, it is invoked on all hitherto created elements 51 * with the same DATA. If one of CLONE, DTOR is non-NULL, then both 52 * have to be. */ 53int vect_clone(struct vect *target, struct vect *source, 54 int (*clone)(void *tgt, void *src, void *data), 55 void (*dtor)(void *elt, void *data), 56 void *data); 57 58/* Destroy VEC, which holds elements of type ELT_TYPE, using DTOR. */ 59#define VECT_CLONE(TGT_VEC, SRC_VEC, ELT_TYPE, CLONE, DTOR, DATA) \ 60 /* xxx GCC-ism necessary to get in the safety latches. */ \ 61 ({ \ 62 struct vect *_source_vec = (SRC_VEC); \ 63 assert(_source_vec->elt_size == sizeof(ELT_TYPE)); \ 64 /* Check that callbacks are typed properly. */ \ 65 void (*_dtor_callback)(ELT_TYPE *, void *) = DTOR; \ 66 int (*_clone_callback)(ELT_TYPE *, \ 67 ELT_TYPE *, void *) = CLONE; \ 68 vect_clone((TGT_VEC), _source_vec, \ 69 (int (*)(void *, void *, void *))_clone_callback, \ 70 (void (*)(void *, void *))_dtor_callback, \ 71 DATA); \ 72 }) 73 74/* Return number of elements in VEC. */ 75size_t vect_size(struct vect *vec); 76 77/* Emptiness predicate. */ 78int vect_empty(struct vect *vec); 79 80/* Accessor. Fetch ELT_NUM-th argument of type ELT_TYPE from the 81 * vector referenced by VECP. */ 82#define VECT_ELEMENT(VECP, ELT_TYPE, ELT_NUM) \ 83 (assert((VECP)->elt_size == sizeof(ELT_TYPE)), \ 84 assert((ELT_NUM) < (VECP)->size), \ 85 ((ELT_TYPE *)(VECP)->data) + (ELT_NUM)) 86 87#define VECT_BACK(VECP, ELT_TYPE) \ 88 VECT_ELEMENT(VECP, ELT_TYPE, (VECP)->size) 89 90/* Copy element referenced by ELTP to the end of VEC. The object 91 * referenced by ELTP is now owned by VECT. Returns 0 if the 92 * operation was successful, or negative value on error. */ 93int vect_pushback(struct vect *vec, void *eltp); 94 95/* Copy element referenced by ELTP to the end of VEC. See 96 * vect_pushback for details. In addition, make a check whether VECP 97 * holds elements of the right size. */ 98#define VECT_PUSHBACK(VECP, ELTP) \ 99 (assert((VECP)->elt_size == sizeof(*(ELTP))), \ 100 vect_pushback((VECP), (ELTP))) 101 102/* Make sure that VEC can hold at least COUNT elements. Return 0 on 103 * success, negative value on failure. */ 104int vect_reserve(struct vect *vec, size_t count); 105 106/* Make sure that VEC can accommodate COUNT additional elements. */ 107int vect_reserve_additional(struct vect *vec, size_t count); 108 109/* Destroy VEC. If DTOR is non-NULL, then it's called on each element 110 * of the vector. DATA is passed to DTOR verbatim. The memory 111 * pointed-to by VEC is not freed. */ 112void vect_destroy(struct vect *vec, 113 void (*dtor)(void *emt, void *data), void *data); 114 115/* Destroy VEC, which holds elements of type ELT_TYPE, using DTOR. */ 116#define VECT_DESTROY(VECP, ELT_TYPE, DTOR, DATA) \ 117 do { \ 118 assert((VECP)->elt_size == sizeof(ELT_TYPE)); \ 119 /* Check that DTOR is typed properly. */ \ 120 void (*_dtor_callback)(ELT_TYPE *, void *) = DTOR; \ 121 vect_destroy((VECP), (void (*)(void *, void *))_dtor_callback, \ 122 DATA); \ 123 } while (0) 124 125#endif /* VECT_H */ 126