Rizin
unix-like reverse engineering framework and cli tools
rz_vector.h
Go to the documentation of this file.
1 #ifndef RZ_VECTOR_H
2 #define RZ_VECTOR_H
3 
4 #include <rz_types.h>
5 #include <rz_util/rz_assert.h>
6 #ifdef __cplusplus
7 extern "C" {
8 #endif
9 
10 /*
11  * RzVector can contain arbitrarily sized elements.
12  * RzPVector uses RzVector internally and always contains void *s
13  *
14  * Thus, for storing pointers it is highly encouraged to always use RzPVector
15  * as it is specifically made for this purpose and is more consistent with RzList,
16  * while RzVector can be used as, for example, a flat array of a struct.
17  *
18  * Notable differences between RzVector and RzPVector:
19  * -------------------------------------------------
20  * When RzVector expects an element to be inserted, for example in rz_vector_push(..., void *x),
21  * this void * value is interpreted as a pointer to the actual data for the element.
22  * => If you use RzVector as a dynamic replacement for (struct SomeStruct)[], you will
23  * pass a struct SomeStruct * to these functions.
24  *
25  * Because RzPVector only handles pointers, the given void * is directly interpreted as the
26  * actual pointer to be inserted.
27  * => If you use RzPVector as a dynamic replacement for (SomeType *)[], you will pass
28  * SomeType * directly to these functions.
29  *
30  * The same differentiation goes for the free functions:
31  * - The element parameter in RzVectorFree is a pointer to the element inside the array.
32  * - The element parameter in RzPVectorFree is the actual pointer stored in the array.
33  *
34  * General Hint:
35  * -------------
36  * remove/pop functions do not reduce the capacity.
37  * Call rz_(p)vector_shrink explicitly if desired.
38  */
39 
40 typedef int (*RzPVectorComparator)(const void *a, const void *b);
41 typedef int (*RzVectorComparator)(const void *a, const void *b);
42 typedef void (*RzVectorFree)(void *e, void *user);
43 typedef void (*RzPVectorFree)(void *e);
44 
45 typedef struct rz_vector_t {
46  void *a;
47  size_t len;
48  size_t capacity;
49  size_t elem_size;
51  void *free_user;
53 
54 // RzPVector directly wraps RzVector for type safety
55 typedef struct rz_pvector_t {
58 
59 // RzVector
60 
61 RZ_API void rz_vector_init(RzVector *vec, size_t elem_size, RzVectorFree free, void *free_user);
62 
63 RZ_API RzVector *rz_vector_new(size_t elem_size, RzVectorFree free, void *free_user);
64 
65 // clears the vector and calls vec->free on every element if set.
66 RZ_API void rz_vector_fini(RzVector *vec);
67 
68 // frees the vector and calls vec->free on every element if set.
69 RZ_API void rz_vector_free(RzVector *vec);
70 
71 // the returned vector will have the same capacity as vec.
73 
74 static inline bool rz_vector_empty(const RzVector *vec) {
75  rz_return_val_if_fail(vec, false);
76  return vec->len == 0;
77 }
78 
80 
81 // returns the length of the vector
82 static inline size_t rz_vector_len(const RzVector *vec) {
83  rz_return_val_if_fail(vec, 0);
84  return vec->len;
85 }
86 
87 // returns a pointer to the offset inside the array where the element of the index lies.
88 static inline void *rz_vector_index_ptr(RzVector *vec, size_t index) {
89  rz_return_val_if_fail(vec && index < vec->capacity, NULL);
90  return (char *)vec->a + vec->elem_size * index;
91 }
92 
93 // returns a pointer to the first element of the vector
94 static inline void *rz_vector_head(RzVector *vec) {
96  return (void *)vec->a;
97 }
98 
99 // returns a pointer to the last element of the vector
100 static inline void *rz_vector_tail(RzVector *vec) {
102  return (char *)vec->a + vec->elem_size * (vec->len - 1);
103 }
104 
105 // helper function to assign an element of size vec->elem_size from elem to p.
106 // elem is a pointer to the actual data to assign!
107 RZ_API void rz_vector_assign(RzVector *vec, void *p, void *elem);
108 
109 // assign the value of size vec->elem_size at elem to vec at the given index.
110 // elem is a pointer to the actual data to assign!
111 RZ_API void *rz_vector_assign_at(RzVector *vec, size_t index, void *elem);
112 
113 // remove the element at the given index and write the content to into.
114 // It is the caller's responsibility to free potential resources associated with the element.
115 RZ_API void rz_vector_remove_at(RzVector *vec, size_t index, void *into);
116 
121 RZ_API void rz_vector_remove_range(RzVector *vec, size_t index, size_t count, void *into);
122 
123 // insert the value of size vec->elem_size at x at the given index.
124 // x is a pointer to the actual data to assign!
125 RZ_API void *rz_vector_insert(RzVector *vec, size_t index, void *x);
126 
127 // insert count values of size vec->elem_size into vec starting at the given index.
128 RZ_API void *rz_vector_insert_range(RzVector *vec, size_t index, void *first, size_t count);
129 
130 // like rz_vector_remove_at for the last element
131 RZ_API void rz_vector_pop(RzVector *vec, void *into);
132 
133 // like rz_vector_remove_at for the first element
134 RZ_API void rz_vector_pop_front(RzVector *vec, void *into);
135 
136 // like rz_vector_insert for the end of vec
137 RZ_API void *rz_vector_push(RzVector *vec, void *x);
138 
139 // like rz_vector_insert for the beginning of vec
140 RZ_API void *rz_vector_push_front(RzVector *vec, void *x);
141 
142 // make sure the capacity is at least capacity.
143 RZ_API void *rz_vector_reserve(RzVector *vec, size_t capacity);
144 
145 // shrink capacity to len.
146 RZ_API void *rz_vector_shrink(RzVector *vec);
147 
155 RZ_API void *rz_vector_flush(RzVector *vec);
156 
157 // sort vector
159 
160 /*
161  * example:
162  *
163  * RzVector *v = ...; // <contains MyStruct>
164  * MyStruct *it;
165  * rz_vector_foreach (v, it) {
166  * // Do something with it
167  * }
168  */
169 #define rz_vector_foreach(vec, it) \
170  if (!rz_vector_empty(vec)) \
171  for (it = (void *)(vec)->a; (char *)it != (char *)(vec)->a + ((vec)->len * (vec)->elem_size); it = (void *)((char *)it + (vec)->elem_size))
172 
173 #define rz_vector_foreach_prev(vec, it) \
174  if (!rz_vector_empty(vec)) \
175  for (it = (void *)((char *)(vec)->a + (((vec)->len - 1) * (vec)->elem_size)); (char *)it != (char *)(vec)->a - (vec)->elem_size; it = (void *)((char *)it - (vec)->elem_size))
176 
177 #define rz_vector_enumerate(vec, it, i) \
178  if (!rz_vector_empty(vec)) \
179  for (it = (void *)(vec)->a, i = 0; i < (vec)->len; it = (void *)((char *)it + (vec)->elem_size), i++)
180 
181 /*
182  * example:
183  *
184  * RzVector *v = ...; // contains {(st64)0, (st64)2, (st64)4, (st64)6, (st64)8};
185  * size_t l;
186  * #define CMP(x, y) x - (*(st64 *)y)
187  * rz_vector_lower_bound (v, 3, l, CMP);
188  * // l == 2
189  */
190 #define rz_vector_lower_bound(vec, x, i, cmp) \
191  do { \
192  size_t h = (vec)->len, m; \
193  for (i = 0; i < h;) { \
194  m = i + ((h - i) >> 1); \
195  if ((cmp(x, ((char *)(vec)->a + (vec)->elem_size * m))) > 0) { \
196  i = m + 1; \
197  } else { \
198  h = m; \
199  } \
200  } \
201  } while (0)
202 
203 #define rz_vector_upper_bound(vec, x, i, cmp) \
204  do { \
205  size_t h = (vec)->len, m; \
206  for (i = 0; i < h;) { \
207  m = i + ((h - i) >> 1); \
208  if ((cmp(x, ((char *)(vec)->a + (vec)->elem_size * m))) < 0) { \
209  h = m; \
210  } else { \
211  i = m + 1; \
212  } \
213  } \
214  } while (0)
215 
216 // RzPVector
217 
219 RZ_API void rz_pvector_fini(RzPVector *vec);
220 
222 
224 
225 // clear the vector and call vec->v.free on every element.
227 
228 // free the vector and call vec->v.free on every element.
229 RZ_API void rz_pvector_free(RzPVector *vec);
230 
231 static inline size_t rz_pvector_len(const RzPVector *vec) {
232  rz_return_val_if_fail(vec, 0);
233  return vec->v.len;
234 }
235 
236 static inline void *rz_pvector_at(const RzPVector *vec, size_t index) {
237  rz_return_val_if_fail(vec && index < vec->v.len, NULL);
238  return ((void **)vec->v.a)[index];
239 }
240 
241 static inline void rz_pvector_set(RzPVector *vec, size_t index, void *e) {
242  rz_return_if_fail(vec && index < vec->v.len);
243  ((void **)vec->v.a)[index] = e;
244 }
245 
246 static inline bool rz_pvector_empty(RzPVector *vec) {
247  return rz_pvector_len(vec) == 0;
248 }
249 
250 // returns a pointer to the offset inside the array where the element of the index lies.
251 static inline void **rz_pvector_index_ptr(RzPVector *vec, size_t index) {
252  rz_return_val_if_fail(vec && index < vec->v.capacity, NULL);
253  return ((void **)vec->v.a) + index;
254 }
255 
256 // same as rz_pvector_index_ptr(<vec>, 0)
257 static inline void **rz_pvector_data(RzPVector *vec) {
259  return (void **)vec->v.a;
260 }
261 
262 // returns the first element of the vector
263 static inline void *rz_pvector_head(RzPVector *vec) {
265  return ((void **)vec->v.a)[0];
266 }
267 
268 // returns the last element of the vector
269 static inline void *rz_pvector_tail(RzPVector *vec) {
271  return ((void **)vec->v.a)[vec->v.len - 1];
272 }
273 
274 // returns the respective pointer inside the vector if x is found or NULL otherwise.
275 RZ_API void **rz_pvector_contains(RzPVector *vec, void *x);
276 
277 // removes and returns the pointer at the given index. Does not call free.
278 RZ_API void *rz_pvector_remove_at(RzPVector *vec, size_t index);
279 
280 // removes the element x, if present. Does not call free.
281 RZ_API void rz_pvector_remove_data(RzPVector *vec, void *x);
282 
283 // like rz_vector_insert, but the pointer x is the actual data to be inserted.
284 static inline void **rz_pvector_insert(RzPVector *vec, size_t index, void *x) {
285  return (void **)rz_vector_insert(&vec->v, index, &x);
286 }
287 
288 // like rz_vector_insert_range.
289 static inline void **rz_pvector_insert_range(RzPVector *vec, size_t index, void **first, size_t count) {
290  return (void **)rz_vector_insert_range(&vec->v, index, first, count);
291 }
292 
293 // like rz_vector_pop, but returns the pointer directly.
294 RZ_API void *rz_pvector_pop(RzPVector *vec);
295 
296 // like rz_vector_pop_front, but returns the pointer directly.
298 
299 // like rz_vector_push, but the pointer x is the actual data to be inserted.
300 static inline void **rz_pvector_push(RzPVector *vec, void *x) {
301  return (void **)rz_vector_push(&vec->v, &x);
302 }
303 
304 // like rz_vector_push_front, but the pointer x is the actual data to be inserted.
305 static inline void **rz_pvector_push_front(RzPVector *vec, void *x) {
306  return (void **)rz_vector_push_front(&vec->v, &x);
307 }
308 
309 // sort vec using quick sort.
311 
312 static inline void **rz_pvector_reserve(RzPVector *vec, size_t capacity) {
313  return (void **)rz_vector_reserve(&vec->v, capacity);
314 }
315 
316 static inline void **rz_pvector_shrink(RzPVector *vec) {
317  return (void **)rz_vector_shrink(&vec->v);
318 }
319 
320 static inline void **rz_pvector_flush(RzPVector *vec) {
321  return (void **)rz_vector_flush(&vec->v);
322 }
323 
324 /*
325  * example:
326  *
327  * RzPVector *v = ...;
328  * void **it;
329  * rz_pvector_foreach (v, it) {
330  * void *p = *it;
331  * // Do something with p
332  * }
333  */
334 #define rz_pvector_foreach(vec, it) \
335  for (it = (void **)(vec)->v.a; (vec)->v.len && it != (void **)(vec)->v.a + (vec)->v.len; it++)
336 
337 // like rz_pvector_foreach() but inverse
338 #define rz_pvector_foreach_prev(vec, it) \
339  for (it = ((vec)->v.len == 0 ? NULL : (void **)(vec)->v.a + (vec)->v.len - 1); it && it != (void **)(vec)->v.a - 1; it--)
340 
341 /*
342  * \brief Find the index of the least element greater than or equal to the lower bound x using binary search
343  * example:
344  *
345  * st64 a[] = { 0, 2, 4, 6, 8 };
346  * size_t index;
347  * #define CMP(x, y) x - y
348  * rz_pvector_lower_bound (v, 3, index, CMP);
349  * // index == 2 (contains value 4)
350  */
351 #define rz_array_lower_bound(array, len, x, i, cmp) \
352  do { \
353  size_t h = len, m; \
354  for (i = 0; i < h;) { \
355  m = i + ((h - i) >> 1); \
356  if (cmp((x), ((array)[m])) > 0) { \
357  i = m + 1; \
358  } else { \
359  h = m; \
360  } \
361  } \
362  } while (0)
363 
364 /*
365  * \brief Find the index of the least element greater than the upper bound x using binary search
366  * example:
367  *
368  * st64 a[] = { 0, 2, 4, 6, 8 };
369  * size_t index;
370  * #define CMP(x, y) x - y
371  * rz_pvector_lower_bound (v, 2, index, CMP);
372  * // index == 2 (contains value 4)
373  */
374 #define rz_array_upper_bound(array, len, x, i, cmp) \
375  do { \
376  size_t h = len, m; \
377  for (i = 0; i < h;) { \
378  m = i + ((h - i) >> 1); \
379  if (cmp((x), ((array)[m])) < 0) { \
380  h = m; \
381  } else { \
382  i = m + 1; \
383  } \
384  } \
385  } while (0)
386 
393 #define rz_array_find(array, x, itr, start, stop, cmp) \
394  do { \
395  for (itr = start; itr < stop; itr++) { \
396  if (cmp((array[itr]), x) == 0) { \
397  break; \
398  } \
399  } \
400  return itr; \
401  } while (0)
402 
403 /*
404  * example:
405  *
406  * RzPVector *v = ...; // contains {(void*)0, (void*)2, (void*)4, (void*)6, (void*)8};
407  * size_t index;
408  * #define CMP(x, y) x - y
409  * rz_pvector_lower_bound (v, (void *)2, index, CMP);
410  * // index == 1
411  */
412 #define rz_pvector_lower_bound(vec, x, i, cmp) \
413  rz_array_lower_bound((void **)(vec)->v.a, (vec)->v.len, x, i, cmp)
414 
415 /*
416  * example:
417  *
418  * RzPVector *v = ...; // contains {(void*)0, (void*)2, (void*)4, (void*)6, (void*)8};
419  * size_t index;
420  * #define CMP(x, y) x - y
421  * rz_pvector_upper_bound (v, (void *)2, index, CMP);
422  * // index == 2
423  */
424 #define rz_pvector_upper_bound(vec, x, i, cmp) \
425  rz_array_upper_bound((void **)(vec)->v.a, (vec)->v.len, x, i, cmp)
426 
427 #ifdef __cplusplus
428 }
429 #endif
430 
431 #endif
#define e(frag)
static RzILOpEffect * cmp(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:942
#define RZ_API
#define NULL
Definition: cris-opc.c:27
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void length
Definition: sflib.h:133
const char * v
Definition: dsignal.c:12
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
void * p
Definition: libc.cpp:67
int x
Definition: mipsasm.c:20
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
static void ** rz_pvector_data(RzPVector *vec)
Definition: rz_vector.h:257
static void * rz_pvector_tail(RzPVector *vec)
Definition: rz_vector.h:269
RZ_API void * rz_vector_assign_at(RzVector *vec, size_t index, void *elem)
Definition: vector.c:119
RZ_API void rz_vector_pop(RzVector *vec, void *into)
Definition: vector.c:184
static void ** rz_pvector_reserve(RzPVector *vec, size_t capacity)
Definition: rz_vector.h:312
static void * rz_vector_index_ptr(RzVector *vec, size_t index)
Definition: rz_vector.h:88
void(* RzVectorFree)(void *e, void *user)
Definition: rz_vector.h:42
RZ_API void rz_pvector_sort(RzPVector *vec, RzPVectorComparator cmp)
Definition: vector.c:408
RZ_API void rz_vector_pop_front(RzVector *vec, void *into)
Definition: vector.c:192
RZ_API void * rz_vector_push_front(RzVector *vec, void *x)
Definition: vector.c:209
RZ_API void * rz_pvector_pop(RzPVector *vec)
Definition: vector.c:372
static void ** rz_pvector_insert_range(RzPVector *vec, size_t index, void **first, size_t count)
Definition: rz_vector.h:289
RZ_API void * rz_vector_flush(RzVector *vec)
Turn the vector into a fixed-size array. This will clear the vector and return an array of its origin...
Definition: vector.c:230
static void ** rz_pvector_push_front(RzPVector *vec, void *x)
Definition: rz_vector.h:305
static void rz_pvector_set(RzPVector *vec, size_t index, void *e)
Definition: rz_vector.h:241
static void ** rz_pvector_index_ptr(RzPVector *vec, size_t index)
Definition: rz_vector.h:251
struct rz_pvector_t RzPVector
RZ_API void rz_pvector_remove_data(RzPVector *vec, void *x)
Definition: vector.c:362
RZ_API void rz_pvector_init(RzPVector *vec, RzPVectorFree free)
Definition: vector.c:298
RZ_API void rz_vector_remove_at(RzVector *vec, size_t index, void *into)
Definition: vector.c:127
RZ_API void rz_pvector_fini(RzPVector *vec)
Definition: vector.c:331
static void * rz_vector_tail(RzVector *vec)
Definition: rz_vector.h:100
RZ_API void * rz_vector_reserve(RzVector *vec, size_t capacity)
Definition: vector.c:214
static size_t rz_pvector_len(const RzPVector *vec)
Definition: rz_vector.h:231
RZ_API void * rz_vector_push(RzVector *vec, void *x)
Definition: vector.c:197
RZ_API RzPVector * rz_pvector_new(RzPVectorFree free)
Definition: vector.c:302
void(* RzPVectorFree)(void *e)
Definition: rz_vector.h:43
static void * rz_vector_head(RzVector *vec)
Definition: rz_vector.h:94
static bool rz_pvector_empty(RzPVector *vec)
Definition: rz_vector.h:246
RZ_API void * rz_pvector_remove_at(RzPVector *vec, size_t index)
Definition: vector.c:355
static void ** rz_pvector_push(RzPVector *vec, void *x)
Definition: rz_vector.h:300
RZ_API void * rz_pvector_pop_front(RzPVector *vec)
Definition: vector.c:379
RZ_API void ** rz_pvector_contains(RzPVector *vec, void *x)
Definition: vector.c:344
static void ** rz_pvector_shrink(RzPVector *vec)
Definition: rz_vector.h:316
RZ_API void rz_vector_fini(RzVector *vec)
Definition: vector.c:61
RZ_API void rz_vector_free(RzVector *vec)
Definition: vector.c:75
RZ_API void rz_pvector_free(RzPVector *vec)
Definition: vector.c:336
RZ_API void * rz_vector_insert_range(RzVector *vec, size_t index, void *first, size_t count)
Definition: vector.c:167
RZ_API RzVector * rz_vector_clone(RzVector *vec)
Definition: vector.c:101
RZ_API RzVector * rz_vector_new(size_t elem_size, RzVectorFree free, void *free_user)
Definition: vector.c:42
RZ_API RzPVector * rz_pvector_new_with_len(RzPVectorFree free, size_t length)
Definition: vector.c:311
RZ_API void rz_vector_clear(RzVector *vec)
Definition: vector.c:68
static void ** rz_pvector_flush(RzPVector *vec)
Definition: rz_vector.h:320
static size_t rz_vector_len(const RzVector *vec)
Definition: rz_vector.h:82
RZ_API void rz_vector_assign(RzVector *vec, void *p, void *elem)
Definition: vector.c:114
RZ_API void rz_vector_init(RzVector *vec, size_t elem_size, RzVectorFree free, void *free_user)
Definition: vector.c:33
static bool rz_vector_empty(const RzVector *vec)
Definition: rz_vector.h:74
RZ_API void * rz_vector_insert(RzVector *vec, size_t index, void *x)
Definition: vector.c:151
RZ_API void rz_vector_remove_range(RzVector *vec, size_t index, size_t count, void *into)
Definition: vector.c:139
int(* RzPVectorComparator)(const void *a, const void *b)
Definition: rz_vector.h:40
RZ_API void rz_pvector_clear(RzPVector *vec)
Definition: vector.c:326
struct rz_vector_t RzVector
static void * rz_pvector_at(const RzPVector *vec, size_t index)
Definition: rz_vector.h:236
int(* RzVectorComparator)(const void *a, const void *b)
Definition: rz_vector.h:41
RZ_API void rz_vector_sort(RzVector *vec, RzVectorComparator cmp, bool reverse)
Sort function for RzVector.
Definition: vector.c:285
static void * rz_pvector_head(RzPVector *vec)
Definition: rz_vector.h:263
RZ_API void * rz_vector_shrink(RzVector *vec)
Definition: vector.c:222
static void ** rz_pvector_insert(RzPVector *vec, size_t index, void *x)
Definition: rz_vector.h:284
static int
Definition: sfsocketcall.h:114
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41
RzVector v
Definition: rz_vector.h:56
RzVectorFree free
Definition: rz_vector.h:50
size_t capacity
Definition: rz_vector.h:48
size_t elem_size
Definition: rz_vector.h:49
void * free_user
Definition: rz_vector.h:51
void * a
Definition: rz_vector.h:46
size_t len
Definition: rz_vector.h:47