Home | History | Annotate | Download | only in ltrace
      1 /*
      2  * This file is part of ltrace.
      3  * Copyright (C) 2011,2012,2013 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.  This is like calling
    100  * vect_erase(VEC, vect_size(VEC)-1, vect_size(VEC), DTOR, DATA);  */
    101 void vect_popback(struct vect *vec,
    102 		  void (*dtor)(void *emt, void *data), void *data);
    103 
    104 #define VECT_POPBACK(VECP, ELT_TYPE, DTOR, DATA)			\
    105 	do								\
    106 		VECT_ERASE((VECP), ELT_TYPE,				\
    107 			   vect_size(VECP) - 1, vect_size(VECP),	\
    108 			   DTOR, DATA);					\
    109 	while (0)
    110 
    111 /* Drop elements START (inclusive) to END (non-inclusive) of VECP.  If
    112  * DTOR is non-NULL, it is called on each of the removed elements.
    113  * DATA is passed verbatim to DTOR.  */
    114 void vect_erase(struct vect *vec, size_t start, size_t end,
    115 		void (*dtor)(void *emt, void *data), void *data);
    116 
    117 #define VECT_ERASE(VECP, ELT_TYPE, START, END, DTOR, DATA)		\
    118 	do {								\
    119 		assert((VECP)->elt_size == sizeof(ELT_TYPE));		\
    120 		/* Check that DTOR is typed properly.  */		\
    121 		void (*_dtor_callback)(ELT_TYPE *, void *) = DTOR;	\
    122 		vect_erase((VECP), (START), (END),			\
    123 			   (void (*)(void *, void *))_dtor_callback, DATA); \
    124 	} while (0)
    125 
    126 /* Copy element referenced by ELTP to the end of VEC.  See
    127  * vect_pushback for details.  In addition, make a check whether VECP
    128  * holds elements of the right size.  */
    129 #define VECT_PUSHBACK(VECP, ELTP)			\
    130 	(assert((VECP)->elt_size == sizeof(*(ELTP))),	\
    131 	 vect_pushback((VECP), (ELTP)))
    132 
    133 /* Make sure that VEC can hold at least COUNT elements.  Return 0 on
    134  * success, negative value on failure.  */
    135 int vect_reserve(struct vect *vec, size_t count);
    136 
    137 /* Make sure that VEC can accommodate COUNT additional elements.  */
    138 int vect_reserve_additional(struct vect *vec, size_t count);
    139 
    140 /* Destroy VEC.  If DTOR is non-NULL, then it's called on each element
    141  * of the vector.  DATA is passed to DTOR verbatim.  The memory
    142  * pointed-to by VEC is not freed.  */
    143 void vect_destroy(struct vect *vec,
    144 		  void (*dtor)(void *emt, void *data), void *data);
    145 
    146 /* Destroy VEC, which holds elements of type ELT_TYPE, using DTOR.  */
    147 #define VECT_DESTROY(VECP, ELT_TYPE, DTOR, DATA)			\
    148 	do {								\
    149 		assert((VECP)->elt_size == sizeof(ELT_TYPE));		\
    150 		/* Check that DTOR is typed properly.  */		\
    151 		void (*_dtor_callback)(ELT_TYPE *, void *) = DTOR;	\
    152 		vect_destroy((VECP), (void (*)(void *, void *))_dtor_callback, \
    153 			     DATA);					\
    154 	} while (0)
    155 
    156 /* Iterate through vector VEC.  See callback.h for notes on iteration
    157  * interfaces.  */
    158 void *vect_each(struct vect *vec, void *start_after,
    159 		enum callback_status (*cb)(void *, void *), void *data);
    160 
    161 #define VECT_EACH(VECP, ELT_TYPE, START_AFTER, CB, DATA)		\
    162 	/* xxx GCC-ism necessary to get in the safety latches.  */	\
    163 	({								\
    164 		assert((VECP)->elt_size == sizeof(ELT_TYPE));		\
    165 		/* Check that CB is typed properly.  */			\
    166 		enum callback_status (*_cb)(ELT_TYPE *, void *) = CB;	\
    167 		ELT_TYPE *_start_after = (START_AFTER);			\
    168 		(ELT_TYPE *)vect_each((VECP), _start_after,		\
    169 				      (enum callback_status		\
    170 				       (*)(void *, void *))_cb,		\
    171 				      DATA);				\
    172 	})
    173 
    174 /* Iterate through vector VEC.  See callback.h for notes on iteration
    175  * interfaces.  */
    176 const void *vect_each_cst(const struct vect *vec, const void *start_after,
    177 			  enum callback_status (*cb)(const void *, void *),
    178 			  void *data);
    179 
    180 #define VECT_EACH_CST(VECP, ELT_TYPE, START_AFTER, CB, DATA)		\
    181 	/* xxx GCC-ism necessary to get in the safety latches.  */	\
    182 	({								\
    183 		assert((VECP)->elt_size == sizeof(ELT_TYPE));		\
    184 		/* Check that CB is typed properly.  */			\
    185 		enum callback_status (*_cb)(const ELT_TYPE *, void *) = CB; \
    186 		const ELT_TYPE *start_after = (START_AFTER);		\
    187 		(const ELT_TYPE *)vect_each_cst((VECP), start_after,	\
    188 						(enum callback_status	\
    189 						 (*)(const void *,	\
    190 						     void *))_cb,	\
    191 						DATA);			\
    192 	})
    193 
    194 /* Call qsort on elements of VECT, with COMPAR as a comparison
    195  * function.  */
    196 void vect_qsort(struct vect *vec, int (*compar)(const void *, const void *));
    197 
    198 #define VECT_QSORT(VECP, ELT_TYPE, COMPAR)				\
    199 	do {								\
    200 		assert((VECP)->elt_size == sizeof(ELT_TYPE));		\
    201 		/* Check that CB is typed properly.  */			\
    202 		int (*_compar)(const ELT_TYPE *, const ELT_TYPE *) = COMPAR; \
    203 		vect_qsort((VECP),					\
    204 			   (int (*)(const void *, const void *))_compar); \
    205 	} while (0)
    206 
    207 
    208 /* A dtor which calls 'free' on elements of a vector.  */
    209 void vect_dtor_string(char **key, void *data);
    210 
    211 #endif /* VECT_H */
    212