quinn-os/pvec.c
2022-07-20 14:37:49 +10:00

136 lines
3.3 KiB
C

#include "inttypes.h"
#include "pvec.h"
#include "memory.h"
#include "string.h"
#include "console.h"
void init_ptr_vector(struct ptr_vector *vec) {
assert(vec != NULL);
memset(vec, 0, sizeof(*vec));
}
void ptr_vector_clear(struct ptr_vector *vec) {
assert(vec != NULL);
vec->len = 0;
memset(vec->ptrs, 0, sizeof(void *) * vec->capacity);
}
void *ptr_vector_get(struct ptr_vector *vec, size_t i) {
assert(vec != NULL);
if (i >= vec->len)
return NULL;
assert(vec->ptrs != NULL);
return vec->ptrs[i];
}
int ptr_vector_put(struct ptr_vector *vec, void *p, size_t i) {
assert(vec != NULL);
if (i >= vec->len)
return 0;
assert(vec->ptrs != NULL);
vec->ptrs[i] = p;
return 1;
}
int ptr_vector_ins(struct ptr_vector *vec, void *p, size_t i) {
assert(vec != NULL);
if (i > vec->len)
return 0;
// Note: If we're inserting at the end of the array
// and we're not reallocating, the call to `memmove()`
// below would take a dest argument pointing immediately
// after the end of the array. It is unclear whether
// this is undefined behavior according to the ISO C
// standard, even though the size in that case would be
// zero, so sidestep the issue by explicitly testing
// for and simply appending in this case.
if (i == vec->len)
return ptr_vector_append(vec, p);
ptr_vector_append(vec, NULL); // Make space in the vector.
memmove(vec->ptrs + i + 1, vec->ptrs + i, (vec->len - (i + 1)) * sizeof(void *));
vec->ptrs[i] = p;
// ++vec->len;
return 1;
}
void *ptr_vector_del(struct ptr_vector *vec, size_t i) {
void *p;
assert(vec != NULL);
if (i >= vec->len)
return NULL;
assert(vec->ptrs != NULL);
p = vec->ptrs[i];
memmove(vec->ptrs + i, vec->ptrs + i + 1, (vec->len - (i + 1)) * sizeof(void *));
--vec->len;
return p;
}
int ptr_vector_append(struct ptr_vector *vec, void *p) {
assert(vec != NULL);
if (vec->len == vec->capacity) {
void **ps;
size_t oldcap = vec->capacity;
if (vec->capacity == 0)
vec->capacity = 1;
else
vec->capacity *= 2;
ps = (void **)dbrealloc(vec->ptrs, vec->capacity * sizeof(void *), "ptr_vector_append");
assert(ps != NULL);
vec->ptrs = ps;
memset(vec->ptrs + oldcap, 0, (vec->capacity - oldcap) * sizeof(void *));
}
vec->ptrs[vec->len] = p;
++vec->len;
return 1;
}
int ptr_vector_append_if_unique(struct ptr_vector *vec, void *p) {
assert(vec != NULL);
for (size_t i = 0; i < vec->len; i++) {
if (vec->ptrs[i] == p) {
return 0;
}
}
return ptr_vector_append(vec, p);
}
size_t ptr_vector_len(struct ptr_vector *vec) {
assert(vec != NULL);
return vec->len;
}
void **ptr_vector_ptrs(struct ptr_vector *vec) {
assert(vec != NULL);
return vec->ptrs;
}
void ptr_vector_apply(struct ptr_vector *vec, void (*f)(void *arg)) {
assert(vec != NULL);
assert(f != NULL);
for (size_t i = 0; i < vec->len; ++i)
f(vec->ptrs[i]);
}
void **consume_ptr_vector(struct ptr_vector *vec) {
if (vec->len == 0) {
return NULL;
}
assert(vec != NULL);
void **ps = (void **)dbrealloc(vec->ptrs, vec->len * sizeof(void *), "consume ptr vector");
assert(ps != NULL);
vec->ptrs = NULL;
vec->len = 0;
vec->capacity = 0;
return ps;
}
void destroy_ptr_vector(struct ptr_vector *vec) {
assert(vec != NULL);
free(vec->ptrs);
vec->ptrs = NULL;
vec->capacity = 0;
vec->len = 0;
}