···11+#ifndef TREE_SITTER_ARRAY_H_
22+#define TREE_SITTER_ARRAY_H_
33+44+#ifdef __cplusplus
55+extern "C" {
66+#endif
77+88+#include "./alloc.h"
99+1010+#include <assert.h>
1111+#include <stdbool.h>
1212+#include <stdint.h>
1313+#include <stdlib.h>
1414+#include <string.h>
1515+1616+#ifdef _MSC_VER
1717+#pragma warning(push)
1818+#pragma warning(disable : 4101)
1919+#elif defined(__GNUC__) || defined(__clang__)
2020+#pragma GCC diagnostic push
2121+#pragma GCC diagnostic ignored "-Wunused-variable"
2222+#endif
2323+2424+#define Array(T) \
2525+ struct { \
2626+ T *contents; \
2727+ uint32_t size; \
2828+ uint32_t capacity; \
2929+ }
3030+3131+/// Initialize an array.
3232+#define array_init(self) \
3333+ ((self)->size = 0, (self)->capacity = 0, (self)->contents = NULL)
3434+3535+/// Create an empty array.
3636+#define array_new() \
3737+ { NULL, 0, 0 }
3838+3939+/// Get a pointer to the element at a given `index` in the array.
4040+#define array_get(self, _index) \
4141+ (assert((uint32_t)(_index) < (self)->size), &(self)->contents[_index])
4242+4343+/// Get a pointer to the first element in the array.
4444+#define array_front(self) array_get(self, 0)
4545+4646+/// Get a pointer to the last element in the array.
4747+#define array_back(self) array_get(self, (self)->size - 1)
4848+4949+/// Clear the array, setting its size to zero. Note that this does not free any
5050+/// memory allocated for the array's contents.
5151+#define array_clear(self) ((self)->size = 0)
5252+5353+/// Reserve `new_capacity` elements of space in the array. If `new_capacity` is
5454+/// less than the array's current capacity, this function has no effect.
5555+#define array_reserve(self, new_capacity) \
5656+ _array__reserve((Array *)(self), array_elem_size(self), new_capacity)
5757+5858+/// Free any memory allocated for this array. Note that this does not free any
5959+/// memory allocated for the array's contents.
6060+#define array_delete(self) _array__delete((Array *)(self))
6161+6262+/// Push a new `element` onto the end of the array.
6363+#define array_push(self, element) \
6464+ (_array__grow((Array *)(self), 1, array_elem_size(self)), \
6565+ (self)->contents[(self)->size++] = (element))
6666+6767+/// Increase the array's size by `count` elements.
6868+/// New elements are zero-initialized.
6969+#define array_grow_by(self, count) \
7070+ do { \
7171+ if ((count) == 0) break; \
7272+ _array__grow((Array *)(self), count, array_elem_size(self)); \
7373+ memset((self)->contents + (self)->size, 0, (count) * array_elem_size(self)); \
7474+ (self)->size += (count); \
7575+ } while (0)
7676+7777+/// Append all elements from one array to the end of another.
7878+#define array_push_all(self, other) \
7979+ array_extend((self), (other)->size, (other)->contents)
8080+8181+/// Append `count` elements to the end of the array, reading their values from the
8282+/// `contents` pointer.
8383+#define array_extend(self, count, contents) \
8484+ _array__splice( \
8585+ (Array *)(self), array_elem_size(self), (self)->size, \
8686+ 0, count, contents \
8787+ )
8888+8989+/// Remove `old_count` elements from the array starting at the given `index`. At
9090+/// the same index, insert `new_count` new elements, reading their values from the
9191+/// `new_contents` pointer.
9292+#define array_splice(self, _index, old_count, new_count, new_contents) \
9393+ _array__splice( \
9494+ (Array *)(self), array_elem_size(self), _index, \
9595+ old_count, new_count, new_contents \
9696+ )
9797+9898+/// Insert one `element` into the array at the given `index`.
9999+#define array_insert(self, _index, element) \
100100+ _array__splice((Array *)(self), array_elem_size(self), _index, 0, 1, &(element))
101101+102102+/// Remove one element from the array at the given `index`.
103103+#define array_erase(self, _index) \
104104+ _array__erase((Array *)(self), array_elem_size(self), _index)
105105+106106+/// Pop the last element off the array, returning the element by value.
107107+#define array_pop(self) ((self)->contents[--(self)->size])
108108+109109+/// Assign the contents of one array to another, reallocating if necessary.
110110+#define array_assign(self, other) \
111111+ _array__assign((Array *)(self), (const Array *)(other), array_elem_size(self))
112112+113113+/// Swap one array with another
114114+#define array_swap(self, other) \
115115+ _array__swap((Array *)(self), (Array *)(other))
116116+117117+/// Get the size of the array contents
118118+#define array_elem_size(self) (sizeof *(self)->contents)
119119+120120+/// Search a sorted array for a given `needle` value, using the given `compare`
121121+/// callback to determine the order.
122122+///
123123+/// If an existing element is found to be equal to `needle`, then the `index`
124124+/// out-parameter is set to the existing value's index, and the `exists`
125125+/// out-parameter is set to true. Otherwise, `index` is set to an index where
126126+/// `needle` should be inserted in order to preserve the sorting, and `exists`
127127+/// is set to false.
128128+#define array_search_sorted_with(self, compare, needle, _index, _exists) \
129129+ _array__search_sorted(self, 0, compare, , needle, _index, _exists)
130130+131131+/// Search a sorted array for a given `needle` value, using integer comparisons
132132+/// of a given struct field (specified with a leading dot) to determine the order.
133133+///
134134+/// See also `array_search_sorted_with`.
135135+#define array_search_sorted_by(self, field, needle, _index, _exists) \
136136+ _array__search_sorted(self, 0, _compare_int, field, needle, _index, _exists)
137137+138138+/// Insert a given `value` into a sorted array, using the given `compare`
139139+/// callback to determine the order.
140140+#define array_insert_sorted_with(self, compare, value) \
141141+ do { \
142142+ unsigned _index, _exists; \
143143+ array_search_sorted_with(self, compare, &(value), &_index, &_exists); \
144144+ if (!_exists) array_insert(self, _index, value); \
145145+ } while (0)
146146+147147+/// Insert a given `value` into a sorted array, using integer comparisons of
148148+/// a given struct field (specified with a leading dot) to determine the order.
149149+///
150150+/// See also `array_search_sorted_by`.
151151+#define array_insert_sorted_by(self, field, value) \
152152+ do { \
153153+ unsigned _index, _exists; \
154154+ array_search_sorted_by(self, field, (value) field, &_index, &_exists); \
155155+ if (!_exists) array_insert(self, _index, value); \
156156+ } while (0)
157157+158158+// Private
159159+160160+typedef Array(void) Array;
161161+162162+/// This is not what you're looking for, see `array_delete`.
163163+static inline void _array__delete(Array *self) {
164164+ if (self->contents) {
165165+ ts_free(self->contents);
166166+ self->contents = NULL;
167167+ self->size = 0;
168168+ self->capacity = 0;
169169+ }
170170+}
171171+172172+/// This is not what you're looking for, see `array_erase`.
173173+static inline void _array__erase(Array *self, size_t element_size,
174174+ uint32_t index) {
175175+ assert(index < self->size);
176176+ char *contents = (char *)self->contents;
177177+ memmove(contents + index * element_size, contents + (index + 1) * element_size,
178178+ (self->size - index - 1) * element_size);
179179+ self->size--;
180180+}
181181+182182+/// This is not what you're looking for, see `array_reserve`.
183183+static inline void _array__reserve(Array *self, size_t element_size, uint32_t new_capacity) {
184184+ if (new_capacity > self->capacity) {
185185+ if (self->contents) {
186186+ self->contents = ts_realloc(self->contents, new_capacity * element_size);
187187+ } else {
188188+ self->contents = ts_malloc(new_capacity * element_size);
189189+ }
190190+ self->capacity = new_capacity;
191191+ }
192192+}
193193+194194+/// This is not what you're looking for, see `array_assign`.
195195+static inline void _array__assign(Array *self, const Array *other, size_t element_size) {
196196+ _array__reserve(self, element_size, other->size);
197197+ self->size = other->size;
198198+ memcpy(self->contents, other->contents, self->size * element_size);
199199+}
200200+201201+/// This is not what you're looking for, see `array_swap`.
202202+static inline void _array__swap(Array *self, Array *other) {
203203+ Array swap = *other;
204204+ *other = *self;
205205+ *self = swap;
206206+}
207207+208208+/// This is not what you're looking for, see `array_push` or `array_grow_by`.
209209+static inline void _array__grow(Array *self, uint32_t count, size_t element_size) {
210210+ uint32_t new_size = self->size + count;
211211+ if (new_size > self->capacity) {
212212+ uint32_t new_capacity = self->capacity * 2;
213213+ if (new_capacity < 8) new_capacity = 8;
214214+ if (new_capacity < new_size) new_capacity = new_size;
215215+ _array__reserve(self, element_size, new_capacity);
216216+ }
217217+}
218218+219219+/// This is not what you're looking for, see `array_splice`.
220220+static inline void _array__splice(Array *self, size_t element_size,
221221+ uint32_t index, uint32_t old_count,
222222+ uint32_t new_count, const void *elements) {
223223+ uint32_t new_size = self->size + new_count - old_count;
224224+ uint32_t old_end = index + old_count;
225225+ uint32_t new_end = index + new_count;
226226+ assert(old_end <= self->size);
227227+228228+ _array__reserve(self, element_size, new_size);
229229+230230+ char *contents = (char *)self->contents;
231231+ if (self->size > old_end) {
232232+ memmove(
233233+ contents + new_end * element_size,
234234+ contents + old_end * element_size,
235235+ (self->size - old_end) * element_size
236236+ );
237237+ }
238238+ if (new_count > 0) {
239239+ if (elements) {
240240+ memcpy(
241241+ (contents + index * element_size),
242242+ elements,
243243+ new_count * element_size
244244+ );
245245+ } else {
246246+ memset(
247247+ (contents + index * element_size),
248248+ 0,
249249+ new_count * element_size
250250+ );
251251+ }
252252+ }
253253+ self->size += new_count - old_count;
254254+}
255255+256256+/// A binary search routine, based on Rust's `std::slice::binary_search_by`.
257257+/// This is not what you're looking for, see `array_search_sorted_with` or `array_search_sorted_by`.
258258+#define _array__search_sorted(self, start, compare, suffix, needle, _index, _exists) \
259259+ do { \
260260+ *(_index) = start; \
261261+ *(_exists) = false; \
262262+ uint32_t size = (self)->size - *(_index); \
263263+ if (size == 0) break; \
264264+ int comparison; \
265265+ while (size > 1) { \
266266+ uint32_t half_size = size / 2; \
267267+ uint32_t mid_index = *(_index) + half_size; \
268268+ comparison = compare(&((self)->contents[mid_index] suffix), (needle)); \
269269+ if (comparison <= 0) *(_index) = mid_index; \
270270+ size -= half_size; \
271271+ } \
272272+ comparison = compare(&((self)->contents[*(_index)] suffix), (needle)); \
273273+ if (comparison == 0) *(_exists) = true; \
274274+ else if (comparison < 0) *(_index) += 1; \
275275+ } while (0)
276276+277277+/// Helper macro for the `_sorted_by` routines below. This takes the left (existing)
278278+/// parameter by reference in order to work with the generic sorting function above.
279279+#define _compare_int(a, b) ((int)*(a) - (int)(b))
280280+281281+#ifdef _MSC_VER
282282+#pragma warning(pop)
283283+#elif defined(__GNUC__) || defined(__clang__)
284284+#pragma GCC diagnostic pop
285285+#endif
286286+287287+#ifdef __cplusplus
288288+}
289289+#endif
290290+291291+#endif // TREE_SITTER_ARRAY_H_