tree-sitter/src/runtime/vector.h

115 lines
3.3 KiB
C
Raw Normal View History

#ifndef RUNTIME_VECTOR_H_
#define RUNTIME_VECTOR_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <string.h>
#include <stdlib.h>
#include <assert.h>
2016-01-28 21:18:57 -08:00
#include <stdbool.h>
2016-01-15 15:08:42 -08:00
#include "runtime/alloc.h"
2016-02-17 14:45:00 -08:00
#define Vector(T) \
struct { \
T *contents; \
size_t size; \
size_t capacity; \
}
2016-02-17 14:45:00 -08:00
#define vector_init(self) \
((self)->size = 0, (self)->capacity = 0, (self)->contents = NULL)
2016-02-17 14:45:00 -08:00
#define vector_get(self, index) \
(assert((size_t)index < (self)->size), &(self)->contents[index])
2016-02-17 14:45:00 -08:00
#define vector_front(self) vector_get(self, 0)
2016-02-17 14:45:00 -08:00
#define vector_back(self) vector_get(self, (self)->size - 1)
2016-02-17 14:45:00 -08:00
#define vector_clear(self) ((self)->size = 0)
2015-11-20 00:01:53 -08:00
2016-02-17 14:45:00 -08:00
#define vector_grow(self, new_capacity) \
vector__grow((VoidVector *)(self), vector__elem_size(self), new_capacity)
2016-02-17 14:45:00 -08:00
#define vector_erase(self, index) \
vector__erase((VoidVector *)(self), vector__elem_size(self), index)
2016-02-17 14:45:00 -08:00
#define vector_delete(self) vector__delete((VoidVector *)self)
2015-11-20 00:01:53 -08:00
2016-02-17 14:45:00 -08:00
#define vector_push(self, element) \
(((self)->size < (self)->capacity || \
vector_grow((self), (self)->capacity * 2)) && \
((self)->contents[(self)->size++] = (element), true))
#define vector_pop(self) ((self)->contents[--(self)->size])
#define vector_reverse(self) \
vector__reverse((VoidVector *)(self), vector__elem_size(self))
#define vector_copy(self) \
{ \
memcpy(ts_calloc((self)->capacity, vector__elem_size(self)), \
(self)->contents, (self)->size *vector__elem_size(self)), \
(self)->size, (self)->capacity, \
}
2016-02-17 14:45:00 -08:00
// Private
typedef Vector(void) VoidVector;
#define vector__elem_size(self) sizeof(*(self)->contents)
static inline void vector__delete(VoidVector *self) {
ts_free(self->contents);
self->contents = NULL;
self->size = 0;
2016-02-17 14:45:00 -08:00
self->capacity = 0;
}
2016-02-17 14:45:00 -08:00
static inline void vector__erase(VoidVector *self, size_t element_size,
size_t index) {
assert(index < self->size);
char *contents = (char *)self->contents;
2016-02-17 14:45:00 -08:00
memmove(contents + index * element_size, contents + (index + 1) * element_size,
(self->size - index - 1) * element_size);
self->size--;
}
2016-02-17 14:45:00 -08:00
static inline bool vector__grow(VoidVector *self, size_t element_size,
size_t new_capacity) {
if (new_capacity == 0)
return true;
2016-02-17 14:45:00 -08:00
void *new_contents;
if (self->contents)
new_contents = ts_realloc(self->contents, new_capacity * element_size);
else
new_contents = ts_calloc(new_capacity, element_size);
if (!new_contents)
return false;
self->capacity = new_capacity;
self->contents = new_contents;
return true;
}
2016-02-17 14:45:00 -08:00
static inline void vector__reverse(VoidVector *self, size_t element_size) {
char swap[element_size];
char *contents = (char *)self->contents;
2016-02-17 14:45:00 -08:00
for (size_t i = 0, limit = self->size / 2; i < limit; i++) {
size_t offset = i * element_size;
size_t reverse_offset = (self->size - 1 - i) * element_size;
memcpy(&swap, contents + offset, element_size);
memcpy(contents + offset, contents + reverse_offset, element_size);
memcpy(contents + reverse_offset, &swap, element_size);
}
}
#ifdef __cplusplus
}
#endif
#endif // RUNTIME_VECTOR_H_