queries
c.h c.scm cpp.h cpp.scm cuda.h cuda.scm glsl.h glsl.scm go.h go.scm javascript.h javascript.scm kotlin.h kotlin.scm lua.h lua.scm odin.h odin.scm php.h php.scm python.h python.scm rust.h rust.scm tcl.h tcl.scm zig.h zig.scmtests
test.c test.cpp test.cu test.cuh test.glsl test.go test.js test.kt test.lua test.odin test.php test.py test.rs test.tcl test.zigvendor
tree-sitter
lib
src
alloc.c alloc.h array.h atomic.h clock.h error_costs.h get_changed_ranges.c get_changed_ranges.h host.h language.c language.h length.h lexer.c lexer.h lib.c node.c parser.c point.h query.c reduce_action.h reusable_node.h stack.c stack.h subtree.c subtree.h tree.c tree.h tree_cursor.c tree_cursor.h unicode.h
vendor/tree-sitter/lib/src/array.h
raw
1#ifndef TREE_SITTER_ARRAY_H_
2#define TREE_SITTER_ARRAY_H_
3
4#ifdef __cplusplus
5extern "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
130typedef Array(void) VoidArray;
131
132#define array__elem_size(self) sizeof(*(self)->contents)
133
134static inline void array__delete(VoidArray *self) {
135 if (self->contents) {
136 ts_free(self->contents);
137 self->contents = NULL;
138 self->size = 0;
139 self->capacity = 0;
140 }
141}
142
143static inline void array__erase(VoidArray *self, size_t element_size,
144 uint32_t index) {
145 assert(index < self->size);
146 char *contents = (char *)self->contents;
147 memmove(contents + index * element_size, contents + (index + 1) * element_size,
148 (self->size - index - 1) * element_size);
149 self->size--;
150}
151
152static inline void array__reserve(VoidArray *self, size_t element_size, uint32_t new_capacity) {
153 if (new_capacity > self->capacity) {
154 if (self->contents) {
155 self->contents = ts_realloc(self->contents, new_capacity * element_size);
156 } else {
157 self->contents = ts_malloc(new_capacity * element_size);
158 }
159 self->capacity = new_capacity;
160 }
161}
162
163static inline void array__assign(VoidArray *self, const VoidArray *other, size_t element_size) {
164 array__reserve(self, element_size, other->size);
165 self->size = other->size;
166 memcpy(self->contents, other->contents, self->size * element_size);
167}
168
169static inline void array__swap(VoidArray *self, VoidArray *other) {
170 VoidArray swap = *other;
171 *other = *self;
172 *self = swap;
173}
174
175static inline void array__grow(VoidArray *self, uint32_t count, size_t element_size) {
176 uint32_t new_size = self->size + count;
177 if (new_size > self->capacity) {
178 uint32_t new_capacity = self->capacity * 2;
179 if (new_capacity < 8) new_capacity = 8;
180 if (new_capacity < new_size) new_capacity = new_size;
181 array__reserve(self, element_size, new_capacity);
182 }
183}
184
185static inline void array__splice(VoidArray *self, size_t element_size,
186 uint32_t index, uint32_t old_count,
187 uint32_t new_count, const void *elements) {
188 uint32_t new_size = self->size + new_count - old_count;
189 uint32_t old_end = index + old_count;
190 uint32_t new_end = index + new_count;
191 assert(old_end <= self->size);
192
193 array__reserve(self, element_size, new_size);
194
195 char *contents = (char *)self->contents;
196 if (self->size > old_end) {
197 memmove(
198 contents + new_end * element_size,
199 contents + old_end * element_size,
200 (self->size - old_end) * element_size
201 );
202 }
203 if (new_count > 0) {
204 if (elements) {
205 memcpy(
206 (contents + index * element_size),
207 elements,
208 new_count * element_size
209 );
210 } else {
211 memset(
212 (contents + index * element_size),
213 0,
214 new_count * element_size
215 );
216 }
217 }
218 self->size += new_count - old_count;
219}
220
221// A binary search routine, based on Rust's `std::slice::binary_search_by`.
222#define array__search_sorted(self, start, compare, suffix, needle, _index, _exists) \
223 do { \
224 *(_index) = start; \
225 *(_exists) = false; \
226 uint32_t size = (self)->size - *(_index); \
227 if (size == 0) break; \
228 int comparison; \
229 while (size > 1) { \
230 uint32_t half_size = size / 2; \
231 uint32_t mid_index = *(_index) + half_size; \
232 comparison = compare(&((self)->contents[mid_index] suffix), (needle)); \
233 if (comparison <= 0) *(_index) = mid_index; \
234 size -= half_size; \
235 } \
236 comparison = compare(&((self)->contents[*(_index)] suffix), (needle)); \
237 if (comparison == 0) *(_exists) = true; \
238 else if (comparison < 0) *(_index) += 1; \
239 } while (0)
240
241// Helper macro for the `_sorted_by` routines below. This takes the left (existing)
242// parameter by reference in order to work with the generic sorting function above.
243#define compare_int(a, b) ((int)*(a) - (int)(b))
244
245#ifdef __cplusplus
246}
247#endif
248
249#endif // TREE_SITTER_ARRAY_H_