util: vector (dynamic array) container
This commit is contained in:
parent
bd347df5d5
commit
6832a76265
91
util/vector.c
Normal file
91
util/vector.c
Normal file
@ -0,0 +1,91 @@
|
||||
|
||||
#include "vector.h"
|
||||
|
||||
#include "../memory/memory.h"
|
||||
#include "string.h"
|
||||
|
||||
|
||||
vector_Vector *vector_Create(uintptr_t objectSize) {
|
||||
vector_Vector *vec = kMalloc(sizeof(vector_Vector));
|
||||
vec->objectSize = objectSize;
|
||||
vec->size = 0;
|
||||
vec->data = 0;
|
||||
|
||||
vec->data = kMalloc(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) {
|
||||
void *newbuf = kMalloc(newcap);
|
||||
memcpy(newbuf, vec->data, vec->size);
|
||||
kFree(vec->data);
|
||||
vec->data = newbuf;
|
||||
vec->cap = newcap;
|
||||
}
|
||||
|
||||
void vector_Destroy(vector_Vector *vec) {
|
||||
kFree(vec->data);
|
||||
kFree(vec);
|
||||
}
|
||||
|
||||
void *vector_Push(vector_Vector *vec, const void *data) {
|
||||
vector_Append(vec, data, 1);
|
||||
return vec->data + vec->size - vec->objectSize;
|
||||
}
|
||||
|
||||
void vector_Append(vector_Vector *vec, const void *data, uintptr_t n) {
|
||||
uintptr_t oldsize = vec->size, addsize = vec->objectSize * n;
|
||||
vector_Resize(vec, oldsize + addsize);
|
||||
|
||||
if (data)
|
||||
memcpy(vec->data + oldsize, data, addsize);
|
||||
else
|
||||
memset(vec->data + oldsize, 0, addsize);
|
||||
}
|
||||
|
||||
void vector_Resize(vector_Vector *vec, uintptr_t size) {
|
||||
uintptr_t newsize = vec->size + size * vec->objectSize;
|
||||
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;
|
||||
}
|
65
util/vector.h
Normal file
65
util/vector.h
Normal file
@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// Vector is an automatic-resizing array.
|
||||
typedef struct {
|
||||
void * data; // actual data buffer
|
||||
uintptr_t size, cap; // size of the data and buffer, in bytes
|
||||
uintptr_t objectSize; // size of the object
|
||||
} vector_Vector;
|
||||
|
||||
// Create allocates a new vector.
|
||||
vector_Vector *vector_Create(uintptr_t objectSize);
|
||||
|
||||
// Destroy properly frees all data related to the structure, and itself.
|
||||
void vector_Destroy(vector_Vector *vec);
|
||||
|
||||
// Push pushes an object at the back of the vector.
|
||||
//
|
||||
// If data is NULL, the data is zeroed.
|
||||
//
|
||||
// Returns a pointer to data.
|
||||
void *vector_Push(vector_Vector *vec, const void *data);
|
||||
|
||||
// Append pushes multiple objects at the back of the buffer.
|
||||
//
|
||||
// If data is NULL, the data is zeroed.
|
||||
void vector_Append(vector_Vector *vec, const void *data, uintptr_t n);
|
||||
|
||||
// Resize resizes the vector to a new number of elements.
|
||||
void vector_Resize(vector_Vector *vec, uintptr_t size);
|
||||
|
||||
// Size returns the number of objects in a vector.
|
||||
uintptr_t vector_Size(vector_Vector *vec);
|
||||
|
||||
// Clear clears a vector, without resizing the buffer.
|
||||
void vector_Clear(vector_Vector *vec);
|
||||
|
||||
// ShrinkBuffer shrinks the internal buffer to exactly the size of the elements.
|
||||
void vector_ShrinkBuffer(vector_Vector *vec);
|
||||
|
||||
// Capacity returns the size of the internal buffer.
|
||||
uintptr_t vector_Capacity(vector_Vector *vec);
|
||||
|
||||
// Reserve reallocates the size of the buffer to CAP objects,
|
||||
// if the current buffer is smaller.
|
||||
void vector_Reserve(vector_Vector *vec, uintptr_t cap);
|
||||
|
||||
// At returns the i-th object of the vector.
|
||||
//
|
||||
// No boundary test is performed.
|
||||
void *vector_At(vector_Vector *vec, uintptr_t i);
|
||||
|
||||
// Data returns the data buffer.
|
||||
void *vector_Data(vector_Vector *vec);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user