2 * This file is part of ltrace.
3 * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc.
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.
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.
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
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. */
36 size_t size; /* In elements. */
37 size_t allocated; /* In elements. */
38 size_t elt_size; /* In bytes. */
41 /* Initialize VEC, which will hold elements of size ELT_SIZE. */
42 void vect_init(struct vect *vec, size_t elt_size);
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)))
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
56 int 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),
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. */ \
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 *, \
71 vect_clone((TGT_VEC), _source_vec, \
72 (int (*)(void *, const void *, \
73 void *))_clone_callback, \
74 (void (*)(void *, void *))_dtor_callback, \
78 /* Return number of elements in VEC. */
79 size_t vect_size(const struct vect *vec);
81 /* Emptiness predicate. */
82 int vect_empty(const struct vect *vec);
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))
91 #define VECT_BACK(VECP, ELT_TYPE) \
92 VECT_ELEMENT(VECP, ELT_TYPE, (VECP)->size - 1)
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. */
97 int vect_pushback(struct vect *vec, void *eltp);
99 /* Drop last element of VECP. */
100 void vect_popback(struct vect *vec);
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)))
109 /* Make sure that VEC can hold at least COUNT elements. Return 0 on
110 * success, negative value on failure. */
111 int vect_reserve(struct vect *vec, size_t count);
113 /* Make sure that VEC can accommodate COUNT additional elements. */
114 int vect_reserve_additional(struct vect *vec, size_t count);
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. */
119 void vect_destroy(struct vect *vec,
120 void (*dtor)(void *emt, void *data), void *data);
122 /* Destroy VEC, which holds elements of type ELT_TYPE, using DTOR. */
123 #define VECT_DESTROY(VECP, ELT_TYPE, DTOR, DATA) \
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, \
132 /* Iterate through vector VEC. See callback.h for notes on iteration
134 void *vect_each(struct vect *vec, void *start_after,
135 enum callback_status (*cb)(void *, void *), void *data);
137 #define VECT_EACH(VECP, ELT_TYPE, START_AFTER, CB, DATA) \
138 /* xxx GCC-ism necessary to get in the safety latches. */ \
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, \