Rizin
unix-like reverse engineering framework and cli tools
vector.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2017-2020 maskray <i@maskray.me>
2 // SPDX-FileCopyrightText: 2017-2020 thestr4ng3r <info@florianmaerkl.de>
3 // SPDX-License-Identifier: LGPL-3.0-only
4 
5 #include "rz_vector.h"
6 
7 // Optimize memory usage on glibc
8 #if __WORDSIZE == 32
9 // Chunk size 24, minus 4 (chunk header), minus 8 for capacity and len, 12 bytes remaining for 3 void *
10 #define INITIAL_VECTOR_LEN 3
11 #else
12 // For __WORDSIZE == 64
13 // Chunk size 48, minus 8 (chunk header), minus 8 for capacity and len, 32 bytes remaining for 4 void *
14 #define INITIAL_VECTOR_LEN 4
15 #endif
16 
17 #define NEXT_VECTOR_CAPACITY (vec->capacity < INITIAL_VECTOR_LEN \
18  ? INITIAL_VECTOR_LEN \
19  : vec->capacity <= 12 ? vec->capacity * 2 \
20  : vec->capacity + (vec->capacity >> 1))
21 
22 #define RESIZE_OR_RETURN_NULL(next_capacity) \
23  do { \
24  size_t new_capacity = next_capacity; \
25  void **new_a = realloc(vec->a, vec->elem_size * new_capacity); \
26  if (!new_a && new_capacity) { \
27  return NULL; \
28  } \
29  vec->a = new_a; \
30  vec->capacity = new_capacity; \
31  } while (0)
32 
33 RZ_API void rz_vector_init(RzVector *vec, size_t elem_size, RzVectorFree free, void *free_user) {
34  rz_return_if_fail(vec);
35  vec->a = NULL;
36  vec->capacity = vec->len = 0;
37  vec->elem_size = elem_size;
38  vec->free = free;
39  vec->free_user = free_user;
40 }
41 
42 RZ_API RzVector *rz_vector_new(size_t elem_size, RzVectorFree free, void *free_user) {
43  RzVector *vec = RZ_NEW(RzVector);
44  if (!vec) {
45  return NULL;
46  }
47  rz_vector_init(vec, elem_size, free, free_user);
48  return vec;
49 }
50 
51 static void vector_free_elems(RzVector *vec) {
52  if (vec->free) {
53  while (vec->len > 0) {
54  vec->free(rz_vector_index_ptr(vec, --vec->len), vec->free_user);
55  }
56  } else {
57  vec->len = 0;
58  }
59 }
60 
62  rz_return_if_fail(vec);
63  rz_vector_clear(vec);
64  vec->free = NULL;
65  vec->free_user = NULL;
66 }
67 
69  rz_return_if_fail(vec);
70  vector_free_elems(vec);
71  RZ_FREE(vec->a);
72  vec->capacity = 0;
73 }
74 
76  if (vec) {
77  rz_vector_fini(vec);
78  free(vec);
79  }
80 }
81 
83  rz_return_val_if_fail(dst && src, false);
84  dst->capacity = src->capacity;
85  dst->len = src->len;
86  dst->elem_size = src->elem_size;
87  dst->free = src->free;
88  dst->free_user = src->free_user;
89  if (!dst->len) {
90  dst->a = NULL;
91  } else {
92  dst->a = malloc(src->elem_size * src->capacity);
93  if (!dst->a) {
94  return false;
95  }
96  memcpy(dst->a, src->a, src->elem_size * src->len);
97  }
98  return true;
99 }
100 
103  RzVector *ret = RZ_NEW(RzVector);
104  if (!ret) {
105  return NULL;
106  }
107  if (!vector_clone(ret, vec)) {
108  free(ret);
109  return NULL;
110  }
111  return ret;
112 }
113 
114 RZ_API void rz_vector_assign(RzVector *vec, void *p, void *elem) {
115  rz_return_if_fail(vec && p && elem);
116  memcpy(p, elem, vec->elem_size);
117 }
118 
119 RZ_API void *rz_vector_assign_at(RzVector *vec, size_t index, void *elem) {
120  void *p = rz_vector_index_ptr(vec, index);
121  if (elem) {
122  rz_vector_assign(vec, p, elem);
123  }
124  return p;
125 }
126 
127 RZ_API void rz_vector_remove_at(RzVector *vec, size_t index, void *into) {
128  rz_return_if_fail(vec);
129  void *p = rz_vector_index_ptr(vec, index);
130  if (into) {
131  rz_vector_assign(vec, into, p);
132  }
133  vec->len--;
134  if (index < vec->len) {
135  memmove(p, (char *)p + vec->elem_size, vec->elem_size * (vec->len - index));
136  }
137 }
138 
139 RZ_API void rz_vector_remove_range(RzVector *vec, size_t index, size_t count, void *into) {
140  rz_return_if_fail(vec && index + count <= vec->len);
141  void *p = rz_vector_index_ptr(vec, index);
142  if (into) {
143  memcpy(into, p, count * vec->elem_size);
144  }
145  vec->len -= count;
146  if (index < vec->len) {
147  memmove(p, (char *)p + vec->elem_size * count, vec->elem_size * (vec->len - index));
148  }
149 }
150 
151 RZ_API void *rz_vector_insert(RzVector *vec, size_t index, void *x) {
152  rz_return_val_if_fail(vec && index <= vec->len, NULL);
153  if (vec->len >= vec->capacity) {
155  }
156  void *p = rz_vector_index_ptr(vec, index);
157  if (index < vec->len) {
158  memmove((char *)p + vec->elem_size, p, vec->elem_size * (vec->len - index));
159  }
160  vec->len++;
161  if (x) {
162  rz_vector_assign(vec, p, x);
163  }
164  return p;
165 }
166 
167 RZ_API void *rz_vector_insert_range(RzVector *vec, size_t index, void *first, size_t count) {
168  rz_return_val_if_fail(vec && index <= vec->len, NULL);
169  if (vec->len + count > vec->capacity) {
171  }
172  size_t sz = count * vec->elem_size;
173  void *p = rz_vector_index_ptr(vec, index);
174  if (index < vec->len) {
175  memmove((char *)p + sz, p, vec->elem_size * (vec->len - index));
176  }
177  vec->len += count;
178  if (first) {
179  memcpy(p, first, sz);
180  }
181  return p;
182 }
183 
184 RZ_API void rz_vector_pop(RzVector *vec, void *into) {
185  rz_return_if_fail(vec);
186  if (into) {
187  rz_vector_assign(vec, into, rz_vector_index_ptr(vec, vec->len - 1));
188  }
189  vec->len--;
190 }
191 
192 RZ_API void rz_vector_pop_front(RzVector *vec, void *into) {
193  rz_return_if_fail(vec);
194  rz_vector_remove_at(vec, 0, into);
195 }
196 
197 RZ_API void *rz_vector_push(RzVector *vec, void *x) {
199  if (vec->len >= vec->capacity) {
201  }
202  void *p = rz_vector_index_ptr(vec, vec->len++);
203  if (x) {
204  rz_vector_assign(vec, p, x);
205  }
206  return p;
207 }
208 
209 RZ_API void *rz_vector_push_front(RzVector *vec, void *x) {
211  return rz_vector_insert(vec, 0, x);
212 }
213 
214 RZ_API void *rz_vector_reserve(RzVector *vec, size_t capacity) {
216  if (vec->capacity < capacity) {
217  RESIZE_OR_RETURN_NULL(capacity);
218  }
219  return vec->a;
220 }
221 
224  if (vec->len < vec->capacity) {
226  }
227  return vec->a;
228 }
229 
232  rz_vector_shrink(vec);
233  void *r = vec->a;
234  vec->a = NULL;
235  vec->capacity = vec->len = 0;
236  return r;
237 }
238 
239 // CLRS Quicksort. It is slow, but simple.
240 #define VEC_INDEX(a, i) (char *)a + elem_size *(i)
241 static void vector_quick_sort(void *a, size_t elem_size, size_t len, RzPVectorComparator cmp, bool reverse) {
243  if (len <= 1) {
244  return;
245  }
246  size_t i = rand() % len, j = 0;
247  void *t, *pivot;
248 
249  t = (void *)malloc(elem_size);
250  pivot = (void *)malloc(elem_size);
251  if (!t || !pivot) {
252  free(t);
253  free(pivot);
254  RZ_LOG_ERROR("Failed to allocate memory\n");
255  return;
256  }
257 
258  memcpy(pivot, VEC_INDEX(a, i), elem_size);
259  memcpy(VEC_INDEX(a, i), VEC_INDEX(a, len - 1), elem_size);
260  for (i = 0; i < len - 1; i++) {
261  if ((cmp(VEC_INDEX(a, i), pivot) < 0 && !reverse) ||
262  (cmp(VEC_INDEX(a, i), pivot) > 0 && reverse)) {
263  memcpy(t, VEC_INDEX(a, i), elem_size);
264  memcpy(VEC_INDEX(a, i), VEC_INDEX(a, j), elem_size);
265  memcpy(VEC_INDEX(a, j), t, elem_size);
266  j++;
267  }
268  }
269  memcpy(VEC_INDEX(a, len - 1), VEC_INDEX(a, j), elem_size);
270  memcpy(VEC_INDEX(a, j), pivot, elem_size);
271  RZ_FREE(t);
272  RZ_FREE(pivot);
273  vector_quick_sort(a, elem_size, j, cmp, reverse);
274  vector_quick_sort(VEC_INDEX(a, j + 1), elem_size, len - j - 1, cmp, reverse);
275 }
276 #undef VEC_INDEX
277 
286  rz_return_if_fail(vec && cmp);
287  vector_quick_sort(vec->a, vec->elem_size, vec->len, cmp, reverse);
288 }
289 
290 // pvector
291 
292 static void pvector_free_elem(void *e, void *user) {
293  void *p = *((void **)e);
294  RzPVectorFree elem_free = (RzPVectorFree)user;
295  elem_free(p);
296 }
297 
299  rz_vector_init(&vec->v, sizeof(void *), free ? pvector_free_elem : NULL, free);
300 }
301 
304  if (!v) {
305  return NULL;
306  }
308  return v;
309 }
310 
313  if (!v) {
314  return NULL;
315  }
316  void **p = rz_pvector_reserve(v, length);
317  if (!p) {
319  return NULL;
320  }
321  memset(p, 0, v->v.elem_size * v->v.capacity);
322  v->v.len = length;
323  return v;
324 }
325 
327  rz_return_if_fail(vec);
328  rz_vector_clear(&vec->v);
329 }
330 
332  rz_return_if_fail(vec);
333  rz_vector_fini(&vec->v);
334 }
335 
337  if (!vec) {
338  return;
339  }
340  rz_vector_fini(&vec->v);
341  free(vec);
342 }
343 
344 RZ_API void **rz_pvector_contains(RzPVector *vec, void *x) {
346  size_t i;
347  for (i = 0; i < vec->v.len; i++) {
348  if (((void **)vec->v.a)[i] == x) {
349  return &((void **)vec->v.a)[i];
350  }
351  }
352  return NULL;
353 }
354 
355 RZ_API void *rz_pvector_remove_at(RzPVector *vec, size_t index) {
357  void *r = rz_pvector_at(vec, index);
358  rz_vector_remove_at(&vec->v, index, NULL);
359  return r;
360 }
361 
363  void **el = rz_pvector_contains(vec, x);
364  if (!el) {
365  return;
366  }
367 
368  size_t index = el - (void **)vec->v.a;
369  rz_vector_remove_at(&vec->v, index, NULL);
370 }
371 
374  void *r = rz_pvector_at(vec, vec->v.len - 1);
375  rz_vector_pop(&vec->v, NULL);
376  return r;
377 }
378 
381  void *r = rz_pvector_at(vec, 0);
382  rz_vector_pop_front(&vec->v, NULL);
383  return r;
384 }
385 
386 // CLRS Quicksort. It is slow, but simple.
387 static void quick_sort(void **a, size_t n, RzPVectorComparator cmp) {
388  if (n <= 1) {
389  return;
390  }
391  size_t i = rand() % n, j = 0;
392  void *t, *pivot = a[i];
393  a[i] = a[n - 1];
394  for (i = 0; i < n - 1; i++) {
395  if (cmp(a[i], pivot) < 0) {
396  t = a[i];
397  a[i] = a[j];
398  a[j] = t;
399  j++;
400  }
401  }
402  a[n - 1] = a[j];
403  a[j] = pivot;
404  quick_sort(a, j, cmp);
405  quick_sort(a + j + 1, n - j - 1, cmp);
406 }
407 
409  rz_return_if_fail(vec && cmp);
410  quick_sort(vec->v.a, vec->v.len, cmp);
411 }
size_t len
Definition: 6502dis.c:15
#define e(frag)
lzma_index ** i
Definition: index.h:629
lzma_index * src
Definition: index.h:567
static RzILOpEffect * cmp(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:942
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
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
return memset(p, 0, total)
void * p
Definition: libc.cpp:67
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
void * malloc(size_t size)
Definition: malloc.c:123
char * dst
Definition: lz4.h:724
int x
Definition: mipsasm.c:20
int n
Definition: mipsasm.c:19
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
#define RZ_NEW(x)
Definition: rz_types.h:285
#define RZ_FREE(x)
Definition: rz_types.h:369
#define RZ_MAX(x, y)
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
void(* RzPVectorFree)(void *e)
Definition: rz_vector.h:43
int(* RzPVectorComparator)(const void *a, const void *b)
Definition: rz_vector.h:40
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
#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
RZ_API void * rz_vector_assign_at(RzVector *vec, size_t index, void *elem)
Definition: vector.c:119
#define VEC_INDEX(a, i)
Definition: vector.c:240
RZ_API void rz_vector_pop(RzVector *vec, void *into)
Definition: vector.c:184
#define NEXT_VECTOR_CAPACITY
Definition: vector.c:17
RZ_API void rz_pvector_sort(RzPVector *vec, RzPVectorComparator cmp)
Definition: vector.c:408
static bool vector_clone(RzVector *dst, RzVector *src)
Definition: vector.c:82
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
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
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 pvector_free_elem(void *e, void *user)
Definition: vector.c:292
RZ_API void * rz_vector_reserve(RzVector *vec, size_t capacity)
Definition: vector.c:214
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
static void quick_sort(void **a, size_t n, RzPVectorComparator cmp)
Definition: vector.c:387
RZ_API void * rz_pvector_remove_at(RzPVector *vec, size_t index)
Definition: vector.c:355
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 vector_free_elems(RzVector *vec)
Definition: vector.c:51
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
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
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
#define RESIZE_OR_RETURN_NULL(next_capacity)
Definition: vector.c:22
RZ_API void rz_pvector_clear(RzPVector *vec)
Definition: vector.c:326
static void vector_quick_sort(void *a, size_t elem_size, size_t len, RzPVectorComparator cmp, bool reverse)
Definition: vector.c:241
RZ_API void rz_vector_sort(RzVector *vec, RzVectorComparator cmp, bool reverse)
Sort function for RzVector.
Definition: vector.c:285
RZ_API void * rz_vector_shrink(RzVector *vec)
Definition: vector.c:222