2015-11-15 09:55:36 -08:00
|
|
|
#ifndef RUNTIME_VECTOR_H_
|
|
|
|
|
#define RUNTIME_VECTOR_H_
|
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
extern "C" {
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdlib.h>
|
2015-11-18 08:47:15 -08:00
|
|
|
#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"
|
2015-11-15 09:55:36 -08:00
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
void *contents;
|
|
|
|
|
size_t size;
|
|
|
|
|
size_t capacity;
|
|
|
|
|
size_t element_size;
|
|
|
|
|
} Vector;
|
|
|
|
|
|
2016-02-04 11:15:46 -08:00
|
|
|
static inline Vector vector_new(size_t element_size) {
|
2015-11-20 00:07:05 -08:00
|
|
|
Vector result;
|
2016-02-04 11:15:46 -08:00
|
|
|
result.contents = NULL;
|
2015-11-20 00:07:05 -08:00
|
|
|
result.size = 0;
|
2016-02-04 11:15:46 -08:00
|
|
|
result.capacity = 0;
|
2015-11-20 00:07:05 -08:00
|
|
|
result.element_size = element_size;
|
2016-02-04 11:15:46 -08:00
|
|
|
return result;
|
|
|
|
|
}
|
2016-01-19 18:07:24 -08:00
|
|
|
|
2016-02-04 11:15:46 -08:00
|
|
|
static inline bool vector_grow(Vector *self, size_t capacity) {
|
2016-02-05 11:18:22 -08:00
|
|
|
if (capacity == 0)
|
|
|
|
|
return true;
|
|
|
|
|
|
2016-02-04 11:15:46 -08:00
|
|
|
void *new_contents;
|
|
|
|
|
if (self->contents)
|
|
|
|
|
new_contents = ts_realloc(self->contents, capacity * self->element_size);
|
|
|
|
|
else
|
|
|
|
|
new_contents = ts_calloc(capacity, self->element_size);
|
2016-01-19 18:07:24 -08:00
|
|
|
|
2016-02-04 11:15:46 -08:00
|
|
|
if (!new_contents)
|
|
|
|
|
return false;
|
|
|
|
|
self->capacity = capacity;
|
|
|
|
|
self->contents = new_contents;
|
|
|
|
|
return true;
|
2015-11-15 09:55:36 -08:00
|
|
|
}
|
|
|
|
|
|
2016-01-19 18:07:24 -08:00
|
|
|
static inline bool vector_valid(Vector *self) {
|
|
|
|
|
return self->element_size > 0;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-20 00:01:53 -08:00
|
|
|
static inline void vector_delete(Vector *self) {
|
2016-01-28 21:18:57 -08:00
|
|
|
if (self->contents) {
|
|
|
|
|
ts_free(self->contents);
|
|
|
|
|
self->contents = NULL;
|
2016-02-04 11:15:46 -08:00
|
|
|
self->size = 0;
|
|
|
|
|
self->capacity = 0;
|
2016-01-28 21:18:57 -08:00
|
|
|
}
|
2015-11-20 00:01:53 -08:00
|
|
|
}
|
|
|
|
|
|
2015-11-18 08:47:15 -08:00
|
|
|
static inline void *vector_get(Vector *self, size_t index) {
|
|
|
|
|
assert(index < self->size);
|
|
|
|
|
return (void *)((char *)self->contents + index * self->element_size);
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-08 12:08:15 -08:00
|
|
|
static inline void vector_set(Vector *self, size_t index, void *entry) {
|
|
|
|
|
assert(index < self->size);
|
|
|
|
|
char *location = (char *)self->contents + index * self->element_size;
|
|
|
|
|
memcpy(location, (char *)entry, self->element_size);
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-20 11:49:04 -08:00
|
|
|
static inline void *vector_back(Vector *self) {
|
2015-11-20 00:01:53 -08:00
|
|
|
assert(self->size > 0);
|
|
|
|
|
return vector_get(self, self->size - 1);
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-04 11:15:46 -08:00
|
|
|
static inline void *vector_pop(Vector *self) {
|
|
|
|
|
void *result = vector_back(self);
|
|
|
|
|
self->size--;
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-18 08:47:15 -08:00
|
|
|
static inline void vector_clear(Vector *self) {
|
|
|
|
|
self->size = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void vector_erase(Vector *self, size_t index) {
|
|
|
|
|
assert(index < self->size);
|
|
|
|
|
char *contents = (char *)self->contents;
|
|
|
|
|
memmove(contents + index * self->element_size,
|
|
|
|
|
contents + (index + 1) * self->element_size,
|
|
|
|
|
(self->size - index - 1) * self->element_size);
|
|
|
|
|
self->size--;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-19 18:07:24 -08:00
|
|
|
static inline bool vector_push(Vector *self, void *entry) {
|
2015-11-15 09:55:36 -08:00
|
|
|
if (self->size == self->capacity) {
|
|
|
|
|
self->capacity += 4;
|
2016-01-22 22:10:18 -07:00
|
|
|
void *contents =
|
|
|
|
|
ts_realloc(self->contents, self->capacity * self->element_size);
|
|
|
|
|
if (!contents)
|
2016-01-19 18:07:24 -08:00
|
|
|
return false;
|
2016-01-22 22:10:18 -07:00
|
|
|
self->contents = contents;
|
2015-11-15 09:55:36 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self->size++;
|
2016-02-08 12:08:15 -08:00
|
|
|
vector_set(self, self->size - 1, entry);
|
2016-01-19 18:07:24 -08:00
|
|
|
return true;
|
2015-11-15 09:55:36 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void vector_reverse(Vector *self) {
|
|
|
|
|
char swap[self->element_size];
|
|
|
|
|
char *contents = (char *)self->contents;
|
|
|
|
|
size_t limit = self->size / 2;
|
|
|
|
|
for (size_t i = 0; i < limit; i++) {
|
|
|
|
|
size_t offset = i * self->element_size;
|
|
|
|
|
size_t reverse_offset = (self->size - 1 - i) * self->element_size;
|
|
|
|
|
memcpy(&swap, contents + offset, self->element_size);
|
|
|
|
|
memcpy(contents + offset, contents + reverse_offset, self->element_size);
|
|
|
|
|
memcpy(contents + reverse_offset, &swap, self->element_size);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline Vector vector_copy(Vector *self) {
|
2015-11-20 00:07:05 -08:00
|
|
|
Vector copy = *self;
|
2016-01-15 15:08:42 -08:00
|
|
|
copy.contents = memcpy(ts_calloc(self->capacity, self->element_size),
|
2015-11-20 11:49:04 -08:00
|
|
|
self->contents, self->size * self->element_size);
|
2015-11-20 00:07:05 -08:00
|
|
|
return copy;
|
2015-11-15 09:55:36 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#endif // RUNTIME_VECTOR_H_
|