2022-08-29 17:27:03 -05:00
|
|
|
#include "vec.h"
|
2022-08-30 17:54:56 -05:00
|
|
|
|
2022-08-30 12:08:36 -05:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2022-08-29 17:27:03 -05:00
|
|
|
|
|
|
|
#define INIT_CAP 8
|
|
|
|
|
|
|
|
static void handle_alloc_error() {
|
|
|
|
printf("Error when allocating memory.\n");
|
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
|
2022-08-30 12:08:36 -05:00
|
|
|
Vec vec_new(size_t data_size) { return vec_cap(data_size, INIT_CAP); }
|
2022-08-29 17:27:03 -05:00
|
|
|
|
|
|
|
Vec vec_cap(size_t data_size, size_t initial_capacity) {
|
|
|
|
Vec v;
|
2022-08-30 12:08:36 -05:00
|
|
|
v.cap = initial_capacity;
|
|
|
|
v.len = 0;
|
2022-08-29 17:27:03 -05:00
|
|
|
v.stride = data_size;
|
2022-08-30 12:08:36 -05:00
|
|
|
v.data = malloc(data_size * initial_capacity);
|
2022-08-29 17:27:03 -05:00
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
2022-08-30 12:08:36 -05:00
|
|
|
static inline void vec_grow(Vec *v, size_t cap) {
|
|
|
|
if (v->cap >= cap)
|
|
|
|
return;
|
|
|
|
size_t new_cap = cap > v->cap * 2 ? cap : v->cap * 2;
|
|
|
|
void *new_data = realloc(v->data, new_cap * v->stride);
|
|
|
|
if (new_data == NULL)
|
|
|
|
handle_alloc_error();
|
2022-08-29 17:27:03 -05:00
|
|
|
v->data = new_data;
|
2022-08-30 12:08:36 -05:00
|
|
|
v->cap = new_cap;
|
2022-08-29 17:27:03 -05:00
|
|
|
}
|
|
|
|
|
2022-08-30 12:08:36 -05:00
|
|
|
void vec_push(Vec *v, void *data) {
|
2022-08-29 17:27:03 -05:00
|
|
|
vec_grow(v, v->len + 1);
|
|
|
|
memcpy(v->data + v->stride * v->len++, data, v->stride);
|
|
|
|
}
|
|
|
|
|
2022-08-30 12:08:36 -05:00
|
|
|
void vec_pop(Vec *v, void *data) {
|
|
|
|
if (v->len == 0) {
|
2022-08-29 17:27:03 -05:00
|
|
|
printf("ERR(vec_pop): Trying to pop an element from an empty vector\n");
|
|
|
|
return;
|
|
|
|
}
|
2022-08-30 12:08:36 -05:00
|
|
|
if (data != NULL)
|
2022-08-29 17:27:03 -05:00
|
|
|
memcpy(data, v->data + v->stride * (v->len - 1), v->stride);
|
|
|
|
v->len--;
|
|
|
|
}
|
|
|
|
|
2022-08-30 12:08:36 -05:00
|
|
|
void *vec_get(Vec *v, size_t index) {
|
|
|
|
if (index >= v->len)
|
|
|
|
return NULL;
|
2022-08-29 17:27:03 -05:00
|
|
|
return v->data + index * v->stride;
|
|
|
|
}
|
|
|
|
|
2022-08-30 12:08:36 -05:00
|
|
|
void vec_insert(Vec *v, void *data, size_t index) {
|
|
|
|
if (index > v->len) {
|
2022-08-29 17:27:03 -05:00
|
|
|
printf("ERR(vec_insert): Trying to insert past the end of the vector.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
vec_grow(v, v->len + 1);
|
|
|
|
|
2022-08-30 12:08:36 -05:00
|
|
|
void *slot = v->data + index * v->stride;
|
|
|
|
if (index < v->len) {
|
2022-08-29 17:27:03 -05:00
|
|
|
memmove(slot + v->stride, slot, (v->len - index) * v->stride);
|
|
|
|
}
|
|
|
|
memcpy(slot, data, v->stride);
|
|
|
|
v->len++;
|
|
|
|
}
|
|
|
|
|
2022-08-30 12:08:36 -05:00
|
|
|
void vec_remove(Vec *v, size_t index, void *data) {
|
|
|
|
if (v->len == 0) {
|
2022-08-29 17:27:03 -05:00
|
|
|
printf("ERR(vec_remove): Trying to remove an element from an empty vector\n");
|
|
|
|
return;
|
|
|
|
}
|
2022-08-30 12:08:36 -05:00
|
|
|
if (index >= v->len) {
|
2022-08-29 17:27:03 -05:00
|
|
|
printf("ERR(vec_remove): Trying to remove past the end of the vector\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-08-30 12:08:36 -05:00
|
|
|
void *slot = v->data + index * v->stride;
|
|
|
|
if (data != NULL)
|
2022-08-29 17:27:03 -05:00
|
|
|
memcpy(data, slot, v->stride);
|
2022-08-30 12:08:36 -05:00
|
|
|
if (index < --v->len)
|
2022-08-29 17:27:03 -05:00
|
|
|
memmove(slot, slot + v->stride, (v->len - index) * v->stride);
|
|
|
|
}
|
|
|
|
|
2022-08-30 12:08:36 -05:00
|
|
|
void vec_clear(Vec *v) { v->len = 0; }
|
2022-08-29 17:27:03 -05:00
|
|
|
|
2022-08-30 12:08:36 -05:00
|
|
|
void vec_extend(Vec *v, void *data, size_t len) {
|
|
|
|
if (len == 0)
|
|
|
|
return;
|
2022-08-29 17:27:03 -05:00
|
|
|
vec_grow(v, v->len + len);
|
|
|
|
memcpy(v->data + v->stride * v->len, data, v->stride * len);
|
|
|
|
v->len += len;
|
|
|
|
}
|
|
|
|
|
2022-08-30 12:08:36 -05:00
|
|
|
void vec_free(Vec v) { free(v.data); }
|