Imported Upstream version 0.7.2
[platform/upstream/ltrace.git] / vect.h
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
33 struct 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.  */
42 void 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.  */
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),
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.  */
79 size_t vect_size(const struct vect *vec);
80
81 /* Emptiness predicate.  */
82 int 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.  */
97 int vect_pushback(struct vect *vec, void *eltp);
98
99 /* Drop last element of VECP.  */
100 void 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.  */
111 int vect_reserve(struct vect *vec, size_t count);
112
113 /* Make sure that VEC can accommodate COUNT additional elements.  */
114 int 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.  */
119 void 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.  */
134 void *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 */