Rizin
unix-like reverse engineering framework and cli tools
array.h
Go to the documentation of this file.
1 #ifndef TREE_SITTER_ARRAY_H_
2 #define TREE_SITTER_ARRAY_H_
3 
4 #ifdef __cplusplus
5 extern "C" {
6 #endif
7 
8 #include <string.h>
9 #include <stdlib.h>
10 #include <stdint.h>
11 #include <assert.h>
12 #include <stdbool.h>
13 #include "./alloc.h"
14 
15 #define Array(T) \
16  struct { \
17  T *contents; \
18  uint32_t size; \
19  uint32_t capacity; \
20  }
21 
22 #define array_init(self) \
23  ((self)->size = 0, (self)->capacity = 0, (self)->contents = NULL)
24 
25 #define array_new() \
26  { NULL, 0, 0 }
27 
28 #define array_get(self, index) \
29  (assert((uint32_t)index < (self)->size), &(self)->contents[index])
30 
31 #define array_front(self) array_get(self, 0)
32 
33 #define array_back(self) array_get(self, (self)->size - 1)
34 
35 #define array_clear(self) ((self)->size = 0)
36 
37 #define array_reserve(self, new_capacity) \
38  array__reserve((VoidArray *)(self), array__elem_size(self), new_capacity)
39 
40 // Free any memory allocated for this array.
41 #define array_delete(self) array__delete((VoidArray *)self)
42 
43 #define array_push(self, element) \
44  (array__grow((VoidArray *)(self), 1, array__elem_size(self)), \
45  (self)->contents[(self)->size++] = (element))
46 
47 // Increase the array's size by a given number of elements, reallocating
48 // if necessary. New elements are zero-initialized.
49 #define array_grow_by(self, count) \
50  (array__grow((VoidArray *)(self), count, array__elem_size(self)), \
51  memset((self)->contents + (self)->size, 0, (count) * array__elem_size(self)), \
52  (self)->size += (count))
53 
54 #define array_push_all(self, other) \
55  array_extend((self), (other)->size, (other)->contents)
56 
57 // Append `count` elements to the end of the array, reading their values from the
58 // `contents` pointer.
59 #define array_extend(self, count, contents) \
60  array__splice( \
61  (VoidArray *)(self), array__elem_size(self), (self)->size, \
62  0, count, contents \
63  )
64 
65 // Remove `old_count` elements from the array starting at the given `index`. At
66 // the same index, insert `new_count` new elements, reading their values from the
67 // `new_contents` pointer.
68 #define array_splice(self, index, old_count, new_count, new_contents) \
69  array__splice( \
70  (VoidArray *)(self), array__elem_size(self), index, \
71  old_count, new_count, new_contents \
72  )
73 
74 // Insert one `element` into the array at the given `index`.
75 #define array_insert(self, index, element) \
76  array__splice((VoidArray *)(self), array__elem_size(self), index, 0, 1, &element)
77 
78 // Remove one `element` from the array at the given `index`.
79 #define array_erase(self, index) \
80  array__erase((VoidArray *)(self), array__elem_size(self), index)
81 
82 #define array_pop(self) ((self)->contents[--(self)->size])
83 
84 #define array_assign(self, other) \
85  array__assign((VoidArray *)(self), (const VoidArray *)(other), array__elem_size(self))
86 
87 #define array_swap(self, other) \
88  array__swap((VoidArray *)(self), (VoidArray *)(other))
89 
90 // Search a sorted array for a given `needle` value, using the given `compare`
91 // callback to determine the order.
92 //
93 // If an existing element is found to be equal to `needle`, then the `index`
94 // out-parameter is set to the existing value's index, and the `exists`
95 // out-parameter is set to true. Otherwise, `index` is set to an index where
96 // `needle` should be inserted in order to preserve the sorting, and `exists`
97 // is set to false.
98 #define array_search_sorted_with(self, compare, needle, index, exists) \
99  array__search_sorted(self, 0, compare, , needle, index, exists)
100 
101 // Search a sorted array for a given `needle` value, using integer comparisons
102 // of a given struct field (specified with a leading dot) to determine the order.
103 //
104 // See also `array_search_sorted_with`.
105 #define array_search_sorted_by(self, field, needle, index, exists) \
106  array__search_sorted(self, 0, _compare_int, field, needle, index, exists)
107 
108 // Insert a given `value` into a sorted array, using the given `compare`
109 // callback to determine the order.
110 #define array_insert_sorted_with(self, compare, value) \
111  do { \
112  unsigned index, exists; \
113  array_search_sorted_with(self, compare, &(value), &index, &exists); \
114  if (!exists) array_insert(self, index, value); \
115  } while (0)
116 
117 // Insert a given `value` into a sorted array, using integer comparisons of
118 // a given struct field (specified with a leading dot) to determine the order.
119 //
120 // See also `array_search_sorted_by`.
121 #define array_insert_sorted_by(self, field, value) \
122  do { \
123  unsigned index, exists; \
124  array_search_sorted_by(self, field, (value) field, &index, &exists); \
125  if (!exists) array_insert(self, index, value); \
126  } while (0)
127 
128 // Private
129 
130 typedef Array(void) VoidArray;
131 
132 #define array__elem_size(self) sizeof(*(self)->contents)
133 
134 static inline void array__delete(VoidArray *self) {
135  ts_free(self->contents);
136  self->contents = NULL;
137  self->size = 0;
138  self->capacity = 0;
139 }
140 
141 static inline void array__erase(VoidArray *self, size_t element_size,
142  uint32_t index) {
143  assert(index < self->size);
144  char *contents = (char *)self->contents;
145  memmove(contents + index * element_size, contents + (index + 1) * element_size,
146  (self->size - index - 1) * element_size);
147  self->size--;
148 }
149 
150 static inline void array__reserve(VoidArray *self, size_t element_size, uint32_t new_capacity) {
151  if (new_capacity > self->capacity) {
152  if (self->contents) {
153  self->contents = ts_realloc(self->contents, new_capacity * element_size);
154  } else {
155  self->contents = ts_malloc(new_capacity * element_size);
156  }
157  self->capacity = new_capacity;
158  }
159 }
160 
161 static inline void array__assign(VoidArray *self, const VoidArray *other, size_t element_size) {
162  array__reserve(self, element_size, other->size);
163  self->size = other->size;
164  memcpy(self->contents, other->contents, self->size * element_size);
165 }
166 
167 static inline void array__swap(VoidArray *self, VoidArray *other) {
168  VoidArray swap = *other;
169  *other = *self;
170  *self = swap;
171 }
172 
173 static inline void array__grow(VoidArray *self, size_t count, size_t element_size) {
174  size_t new_size = self->size + count;
175  if (new_size > self->capacity) {
176  size_t new_capacity = self->capacity * 2;
177  if (new_capacity < 8) new_capacity = 8;
178  if (new_capacity < new_size) new_capacity = new_size;
179  array__reserve(self, element_size, new_capacity);
180  }
181 }
182 
183 static inline void array__splice(VoidArray *self, size_t element_size,
184  uint32_t index, uint32_t old_count,
185  uint32_t new_count, const void *elements) {
186  uint32_t new_size = self->size + new_count - old_count;
187  uint32_t old_end = index + old_count;
188  uint32_t new_end = index + new_count;
189  assert(old_end <= self->size);
190 
191  array__reserve(self, element_size, new_size);
192 
193  char *contents = (char *)self->contents;
194  if (self->size > old_end) {
195  memmove(
196  contents + new_end * element_size,
197  contents + old_end * element_size,
198  (self->size - old_end) * element_size
199  );
200  }
201  if (new_count > 0) {
202  if (elements) {
203  memcpy(
204  (contents + index * element_size),
205  elements,
206  new_count * element_size
207  );
208  } else {
209  memset(
210  (contents + index * element_size),
211  0,
212  new_count * element_size
213  );
214  }
215  }
216  self->size += new_count - old_count;
217 }
218 
219 // A binary search routine, based on Rust's `std::slice::binary_search_by`.
220 #define array__search_sorted(self, start, compare, suffix, needle, index, exists) \
221  do { \
222  *(index) = start; \
223  *(exists) = false; \
224  uint32_t size = (self)->size - *(index); \
225  if (size == 0) break; \
226  int comparison; \
227  while (size > 1) { \
228  uint32_t half_size = size / 2; \
229  uint32_t mid_index = *(index) + half_size; \
230  comparison = compare(&((self)->contents[mid_index] suffix), (needle)); \
231  if (comparison <= 0) *(index) = mid_index; \
232  size -= half_size; \
233  } \
234  comparison = compare(&((self)->contents[*(index)] suffix), (needle)); \
235  if (comparison == 0) *(exists) = true; \
236  else if (comparison < 0) *(index) += 1; \
237  } while (0)
238 
239 // Helper macro for the `_sorted_by` routines below. This takes the left (existing)
240 // parameter by reference in order to work with the generic sorting function above.
241 #define _compare_int(a, b) ((int)*(a) - (int)(b))
242 
243 #ifdef __cplusplus
244 }
245 #endif
246 
247 #endif // TREE_SITTER_ARRAY_H_
#define ts_realloc
Definition: alloc.h:27
#define ts_malloc
Definition: alloc.h:21
#define ts_free
Definition: alloc.h:30
static void array__grow(VoidArray *self, size_t count, size_t element_size)
Definition: array.h:173
static void array__splice(VoidArray *self, size_t element_size, uint32_t index, uint32_t old_count, uint32_t new_count, const void *elements)
Definition: array.h:183
#define Array(T)
Definition: array.h:15
static void array__reserve(VoidArray *self, size_t element_size, uint32_t new_capacity)
Definition: array.h:150
static void array__erase(VoidArray *self, size_t element_size, uint32_t index)
Definition: array.h:141
static void array__swap(VoidArray *self, VoidArray *other)
Definition: array.h:167
static void array__assign(VoidArray *self, const VoidArray *other, size_t element_size)
Definition: array.h:161
static void array__delete(VoidArray *self)
Definition: array.h:134
#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
voidpf void uLong size
Definition: ioapi.h:138
return memset(p, 0, total)
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
assert(limit<=UINT32_MAX/2)
#define swap(a, b)
Definition: qsort.h:111
unsigned int uint32_t
Definition: sftypes.h:29
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4