libflint/src/vector.c

174 lines
3.7 KiB
C
Raw Normal View History

2023-10-25 14:56:41 +00:00
#include <stdlib.h>
#include <stdio.h>
2023-10-25 16:02:56 +00:00
#ifdef __linux__
#include <bsd/stdlib.h>
#endif
2023-11-29 21:40:41 +00:00
#include "lfvector.h"
2023-10-25 14:56:41 +00:00
#define VEC_INIT_CAP 2
int vec_init(Vector *vec, void (*destroy)(void *data)) {
return vec_init_with_capacity(vec, destroy, VEC_INIT_CAP);
}
int vec_init_with_capacity(Vector *vec, void (*destroy)(void *data), size_t capacity) {
if (vec == NULL) {
return -1;
}
vec->destroy = destroy;
vec_len(vec) = 0;
vec->capacity = capacity;
vec->elements = malloc(sizeof (void*) * capacity);
if (vec->elements == NULL) {
return -1;
}
memset(vec->elements, 0, vec->capacity * sizeof(void *));
return 0;
}
static int vec_grow(Vector *const vec) {
vec->capacity *= 2;
2023-10-30 21:22:11 +00:00
#ifdef __OpenBSD__
vec->elements = reallocarray(vec->elements, vec->capacity, sizeof(void *));
#else
2023-10-25 14:56:41 +00:00
vec->elements = reallocf(vec->elements, sizeof(void *) * vec->capacity);
2023-10-30 21:22:11 +00:00
#endif
2023-10-25 14:56:41 +00:00
if (vec->elements == NULL) {
return -1;
}
return 0;
}
void vec_destroy(Vector *vec) {
if (vec->destroy) {
for (size_t i = 0; i < vec_len(vec); ++i) {
vec->destroy(vec->elements[i]);
}
}
}
int vec_insert(Vector *vec, void *data, size_t index) {
if (vec_len(vec) + 1 >= vec->capacity) {
if (vec_grow(vec) != 0) {
return -1;
}
}
if (index > vec_len(vec)) {
return -1;
}
if (index < vec_len(vec)) {
void *a = vec->elements[index];
vec->elements[index] = data;
void *b = NULL;
for (size_t i = index + 1; i <= vec_len(vec); ++i) {
b = vec->elements[i];
vec->elements[i] = a;
a = b;
}
} else /* index == vec_len(vec) */ {
vec->elements[index] = data;
}
vec_len(vec) += 1;
return 0;
}
int vec_push(Vector *vec, void *data) {
return vec_insert(vec, data, vec_len(vec));
}
void *vec_safe_at(Vector *vec, size_t index) {
if (index >= vec_len(vec)) {
return NULL;
}
return vec->elements[index];
}
void *vec_remove(Vector *vec, size_t index) {
if (index >= vec_len(vec)) {
return NULL;
}
void *r = vec_at(vec, index);
for (size_t i = index + 1; i < vec_len(vec); ++i) {
vec->elements[i - 1] = vec->elements[i];
}
vec->elements[vec_len(vec) - 1] = NULL;
vec->length -= 1;
return r;
}
2023-10-25 15:42:38 +00:00
int vec_shrink(Vector *vec) {
if (vec_len(vec) == vec_cap(vec)) {
return 0;
}
vec->capacity = vec_len(vec);
2023-10-30 21:22:11 +00:00
#ifdef __OpenBSD__
vec->elements = reallocarray(vec->elements, vec->capacity, sizeof(void *));
#else
vec->elements = reallocf(vec->elements, sizeof(void *) * vec->capacity);
#endif
2023-10-25 15:42:38 +00:00
if (vec->elements == NULL) {
return -1;
}
return 0;
}
2023-11-29 22:39:59 +00:00
const void *vec_min(const Vector *vec, int(*cmp)(const void *a, const void *b)) {
void *a = vec->elements[0];
for (size_t i = 1; i < vec_len(vec); ++i) {
2023-11-30 16:57:01 +00:00
if (cmp(a, vec->elements[i]) > 0) {
2023-11-29 22:39:59 +00:00
a = vec->elements[i];
}
}
return a;
}
const void *vec_max(const Vector *vec, int(*cmp)(const void *a, const void *b)) {
void *a = vec->elements[0];
for (size_t i = 1; i < vec_len(vec); ++i) {
2023-11-30 16:57:01 +00:00
if (cmp(a, vec->elements[i]) < 0) {
2023-11-29 22:39:59 +00:00
a = vec->elements[i];
}
}
return a;
}
int vec_cmp_int(const void *a, const void *b) {
const int x = *(int*)a;
const int y = *(int*)b;
if (x > y) {
return 1;
}
if (x < y) {
return -1;
}
return 0;
}
int vec_cmp_char(const void *a, const void *b) {
const char x = *(int*)a;
const char y = *(int*)b;
if (x > y) {
return 1;
}
if (x < y) {
return -1;
}
return 0;
}