2024-02-29 09:48:29 +08:00
|
|
|
|
|
|
|
#include "vector.h"
|
|
|
|
|
|
|
|
#include "string.h"
|
|
|
|
#include "stdlib.h"
|
2024-04-24 21:30:28 +08:00
|
|
|
#include "assert.h"
|
2024-02-29 09:48:29 +08:00
|
|
|
|
|
|
|
|
|
|
|
vector_Vector *vector_Create(uintptr_t objectSize) {
|
|
|
|
vector_Vector *vec = malloc(sizeof(vector_Vector));
|
|
|
|
vec->objectSize = objectSize;
|
|
|
|
vec->size = 0;
|
|
|
|
vec->data = 0;
|
|
|
|
|
|
|
|
vec->data = malloc(objectSize);
|
|
|
|
vec->cap = objectSize;
|
|
|
|
|
|
|
|
return vec;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Resizes the underlying buffer to a new capacity
|
|
|
|
static inline void __vector_Rebuffer(vector_Vector *vec, uintptr_t newcap) {
|
2024-04-24 21:30:28 +08:00
|
|
|
ASSERT(newcap >= vec->size);
|
2024-02-29 09:48:29 +08:00
|
|
|
void *newbuf = malloc(newcap);
|
|
|
|
memcpy(newbuf, vec->data, vec->size);
|
|
|
|
free(vec->data);
|
|
|
|
vec->data = newbuf;
|
|
|
|
vec->cap = newcap;
|
|
|
|
}
|
|
|
|
|
|
|
|
void vector_Destroy(vector_Vector *vec) {
|
|
|
|
free(vec->data);
|
|
|
|
free(vec);
|
|
|
|
}
|
|
|
|
|
|
|
|
void *vector_Push(vector_Vector *vec, const void *data) {
|
|
|
|
vector_Append(vec, data, 1);
|
|
|
|
return vec->data + vec->size - vec->objectSize;
|
|
|
|
}
|
|
|
|
|
2024-02-29 16:17:55 +08:00
|
|
|
bool vector_Pop(vector_Vector *vec, void *out_data) {
|
|
|
|
if (!vector_Size(vec))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (out_data)
|
|
|
|
memcpy(out_data, vec->data + (vec->size - vec->objectSize), vec->objectSize);
|
|
|
|
|
|
|
|
vector_Resize(vec, vector_Size(vec) - 1);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-02-29 09:48:29 +08:00
|
|
|
void vector_Append(vector_Vector *vec, const void *data, uintptr_t n) {
|
|
|
|
uintptr_t oldsize = vec->size, addsize = vec->objectSize * n;
|
2024-04-24 21:30:28 +08:00
|
|
|
vector_Resize(vec, vector_Size(vec) + n);
|
2024-02-29 09:48:29 +08:00
|
|
|
|
|
|
|
if (data)
|
|
|
|
memcpy(vec->data + oldsize, data, addsize);
|
|
|
|
else
|
|
|
|
memset(vec->data + oldsize, 0, addsize);
|
|
|
|
}
|
|
|
|
|
|
|
|
void vector_Resize(vector_Vector *vec, uintptr_t size) {
|
2024-04-24 21:30:28 +08:00
|
|
|
uintptr_t newsize = size * vec->objectSize;
|
2024-02-29 09:48:29 +08:00
|
|
|
if (newsize > vec->cap) {
|
|
|
|
// grow the buffer exponentially
|
|
|
|
uint64_t newcap = vec->cap;
|
|
|
|
while (newcap < newsize)
|
|
|
|
newcap *= 2;
|
|
|
|
__vector_Rebuffer(vec, newcap);
|
|
|
|
}
|
|
|
|
vec->size = newsize;
|
|
|
|
}
|
|
|
|
|
|
|
|
uintptr_t vector_Size(vector_Vector *vec) {
|
|
|
|
return vec->size / vec->objectSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
void vector_Clear(vector_Vector *vec) {
|
|
|
|
vec->size = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void vector_ShrinkBuffer(vector_Vector *vec) {
|
|
|
|
if (vec->size != vec->cap)
|
|
|
|
__vector_Rebuffer(vec, vec->size);
|
|
|
|
}
|
|
|
|
|
|
|
|
uintptr_t vector_Capacity(vector_Vector *vec) {
|
|
|
|
return vec->cap / vec->objectSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
void vector_Reserve(vector_Vector *vec, uintptr_t cap) {
|
|
|
|
uintptr_t newcap = vec->objectSize * cap;
|
|
|
|
if (newcap > vec->cap)
|
|
|
|
__vector_Rebuffer(vec, newcap);
|
|
|
|
}
|
|
|
|
|
|
|
|
void *vector_At(vector_Vector *vec, uintptr_t i) {
|
|
|
|
return vec->data + vec->objectSize * i;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Data returns the data buffer.
|
|
|
|
void *vector_Data(vector_Vector *vec) {
|
|
|
|
return vec->data;
|
|
|
|
}
|
2024-04-24 21:30:28 +08:00
|
|
|
|
|
|
|
void *vector_Back(vector_Vector *vec) {
|
|
|
|
return vector_At(vec, vector_Size(vec) - 1);
|
|
|
|
}
|