initial
This commit is contained in:
179
src/dynarr.c
Normal file
179
src/dynarr.c
Normal file
@@ -0,0 +1,179 @@
|
||||
#include <dynarr.h>
|
||||
|
||||
DynArr* DynArr_create(size_t elemSize, size_t capacity) {
|
||||
DynArr* p = (DynArr*)malloc(sizeof(DynArr));
|
||||
if (!p) return NULL;
|
||||
|
||||
p->elemSize = elemSize;
|
||||
p->capacity = capacity;
|
||||
p->data = malloc(elemSize * capacity);
|
||||
if (!p->data) {
|
||||
free(p);
|
||||
return NULL;
|
||||
}
|
||||
p->size = 0;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
// Reserve n blocks in arary; New size will be n, NOT size + n; Reserving less memory that current will fail, use prune instead.
|
||||
void DynArr_reserve(DynArr* p, size_t n) {
|
||||
if (n <= p->capacity) {
|
||||
printf("reserve ignored; attempted to reserve less or equal to current capacity\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (n > DYNARR_MAX_CAPACITY) {
|
||||
printf("reserve ignored; attempted to reserve over 32 bits\n");
|
||||
return;
|
||||
}
|
||||
|
||||
void* new_data = realloc(p->data, n * p->elemSize);
|
||||
if (!new_data) {
|
||||
printf("reserve failed\n");
|
||||
exit(1);
|
||||
}
|
||||
p->data = new_data;
|
||||
p->capacity = n;
|
||||
}
|
||||
|
||||
// Push data into a new block at the end of the array; If value is NULL, the new block will be zeroed.
|
||||
void* DynArr_push_back(DynArr* p, void* value) {
|
||||
//if (value == NULL) {
|
||||
// printf("push_back ignored; value is null");
|
||||
// return NULL;
|
||||
//}
|
||||
|
||||
if (p->size >= p->capacity) {
|
||||
size_t new_cap = (p->capacity == 0) ? 1 : p->capacity * 2;
|
||||
|
||||
if (new_cap < p->capacity || new_cap > DYNARR_MAX_CAPACITY) {
|
||||
printf("push_back ignored; capacity overflow\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* new_data = realloc(p->data, new_cap * p->elemSize);
|
||||
if (!new_data) {
|
||||
printf("push failed\n");
|
||||
exit(1);
|
||||
}
|
||||
p->capacity = new_cap;
|
||||
p->data = new_data;
|
||||
}
|
||||
|
||||
void* dst = (void*)((char*)p->data + (p->size * p->elemSize));
|
||||
|
||||
if (value == NULL) {
|
||||
memset(dst, 0, p->elemSize); // Handle NULL value.
|
||||
} else {
|
||||
memcpy((char*)dst, value, p->elemSize);
|
||||
}
|
||||
|
||||
p->size++;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
// Remove the last block in the array.
|
||||
void DynArr_pop_back(DynArr* p) {
|
||||
if (p->size == 0) {
|
||||
printf("pop_back ignored; size is 0\n");
|
||||
return;
|
||||
}
|
||||
|
||||
p->size--; // Will automatically overwrite that memory naturally
|
||||
}
|
||||
|
||||
// Remove first block from array.
|
||||
void DynArr_pop_front(DynArr* p) {
|
||||
if (p->size == 0) {
|
||||
printf("pop_front ignored; size is 0\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memmove(
|
||||
(char*)p->data,
|
||||
(char*)p->data + p->elemSize,
|
||||
(p->size - 1) * p->elemSize
|
||||
);
|
||||
|
||||
p->size--;
|
||||
}
|
||||
|
||||
// Remove index from array. This moves all blocks after the index block.
|
||||
void DynArr_remove(DynArr* p, size_t index) {
|
||||
if (index >= p->size) return;
|
||||
|
||||
memmove(
|
||||
(char*)p->data + (index * p->elemSize),
|
||||
(char*)p->data + (index + 1) * p->elemSize,
|
||||
(p->size - index - 1) * p->elemSize
|
||||
);
|
||||
|
||||
p->size--;
|
||||
}
|
||||
|
||||
// Erase the array. This will not free unused blocks.
|
||||
void DynArr_erase(DynArr* p) {
|
||||
p->size = 0;
|
||||
}
|
||||
|
||||
// Prune and free unused blocks. If pruning to zero, ensure to reserve after.
|
||||
void DynArr_prune(DynArr* p) {
|
||||
void* new_data = realloc(p->data, (p->size == 0 ? 1 : p->size) * p->elemSize);
|
||||
if (!new_data) {
|
||||
printf("pruning failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
p->data = new_data;
|
||||
p->capacity = p->size;
|
||||
}
|
||||
|
||||
// Get a pointer to a block by index
|
||||
void* DynArr_at(DynArr* p, size_t index) {
|
||||
if (index >= p->size) return NULL;
|
||||
return (char*)p->data + (index * p->elemSize);
|
||||
}
|
||||
|
||||
// Get the index by block pointer
|
||||
size_t DynArr_at_ptr(DynArr* p, void* ptr) {
|
||||
if (!p || !ptr) {
|
||||
printf("invalid pointer\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < p->size; i++) {
|
||||
if ((void*)(((char*)p->data) + (i * p->elemSize)) == ptr) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
// If for some reason the array has 2^64 elements in it, then fuck it, I guess we'll just crash, I don't care.
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Get size
|
||||
size_t DynArr_size(DynArr* p) {
|
||||
return p->size;
|
||||
}
|
||||
|
||||
// Get element size
|
||||
size_t DynArr_elemSize(DynArr* p) {
|
||||
return p->elemSize;
|
||||
}
|
||||
|
||||
// Get capacity
|
||||
size_t DynArr_capacity(DynArr* p) {
|
||||
return p->capacity;
|
||||
}
|
||||
|
||||
void DynArr_destroy(DynArr* p) {
|
||||
if (!p) return;
|
||||
free(p->data);
|
||||
free(p);
|
||||
}
|
||||
|
||||
void* DynArr_c_arr(DynArr* p) {
|
||||
return p->data;
|
||||
}
|
||||
Reference in New Issue
Block a user