mirror of
https://github.com/thepigeongenerator/sdl_template.git
synced 2025-12-17 05:55:47 +01:00
add resizeing functions
This commit is contained in:
@@ -2,11 +2,15 @@
|
|||||||
#define DYNARR_H
|
#define DYNARR_H
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define DYNARR_COMB2(a, b) a##b
|
#define DYNARR_COMB2(a, b) a##b
|
||||||
#define DYNARR_COMB1(a, b) DYNARR_COMB2(a, b)
|
#define DYNARR_COMB1(a, b) DYNARR_COMB2(a, b)
|
||||||
#endif // DYNARR_H
|
#endif // DYNARR_H
|
||||||
|
|
||||||
|
#define DYNARR_TYPE float
|
||||||
|
|
||||||
#ifdef DYNARR_TYPE
|
#ifdef DYNARR_TYPE
|
||||||
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
// customising the linkage
|
// customising the linkage
|
||||||
@@ -19,14 +23,9 @@
|
|||||||
#define DYNARR_NAME DYNARR_COMB1(dynarr_, DYNARR_TYPE)
|
#define DYNARR_NAME DYNARR_COMB1(dynarr_, DYNARR_TYPE)
|
||||||
#endif // DYNARR_NAME
|
#endif // DYNARR_NAME
|
||||||
|
|
||||||
#define DYNARR_init DYNARR_COMB1(DYNARR_NAME, _init) // name of the initialization funcition
|
#define DYNARR_FUNC(name) DYNARR_COMB1(DYNARR_NAME, _##name) // name of the initialization funcition
|
||||||
#define DYNARR_add DYNARR_COMB1(DYNARR_NAME, _add) // name of the addition function
|
|
||||||
#define DYNARR_remove DYNARR_COMB1(DYNARR_NAME, _remove) // name of the removal function
|
|
||||||
#define DYNARR_free DYNARR_COMB1(DYNARR_NAME, _free) // name of the freeing function
|
|
||||||
// TODO: add shrink function (call when count < cap / 4)
|
// TODO: add shrink function (call when count < cap / 4)
|
||||||
// TODO: add resize function
|
|
||||||
// TODO: add bulk addition function
|
// TODO: add bulk addition function
|
||||||
// TODO: add bulk addition function (doesn't respec growth factor)
|
|
||||||
// TODO: add bulk deletion function
|
// TODO: add bulk deletion function
|
||||||
|
|
||||||
|
|
||||||
@@ -37,31 +36,50 @@ typedef struct {
|
|||||||
size_t cap; // contains the capacity of the dynamic array
|
size_t cap; // contains the capacity of the dynamic array
|
||||||
} DYNARR_NAME;
|
} DYNARR_NAME;
|
||||||
|
|
||||||
// initializes the dynamic array with a specific capacity (dat may be null if malloc fails)
|
// adds an exact number of items to the capacity, does not respect scaling
|
||||||
DYNARR_LINKAGE DYNARR_NAME DYNARR_init(const size_t cap) {
|
// returns 0 upon success, 1 upon failure
|
||||||
return (DYNARR_NAME){
|
DYNARR_LINKAGE uint8_t DYNARR_FUNC(resize_exact)(DYNARR_NAME* arr, size_t ncap) {
|
||||||
malloc(cap * sizeof(DYNARR_TYPE)),
|
if (ncap < arr->count) return 1; // the new capacity is smaller than the count, this is very likely unintentional
|
||||||
0,
|
if (ncap == arr->cap) return 0; // the capacity is already the new capacity; no work needs to be done
|
||||||
cap,
|
|
||||||
};
|
// (re)allocate the memory for the array
|
||||||
|
DYNARR_TYPE* nptr = (arr->dat == NULL)
|
||||||
|
? malloc(ncap * sizeof(DYNARR_TYPE))
|
||||||
|
: realloc(arr->dat, ncap * sizeof(DYNARR_TYPE));
|
||||||
|
|
||||||
|
// if memory (re)allocation failed; return
|
||||||
|
if (nptr == NULL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
arr->dat = nptr;
|
||||||
|
arr->cap = ncap;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// resizes the array by adding `nitems` to the count, respects capacity scaling
|
||||||
|
// returns 0 upon success, 1 upon failure
|
||||||
|
DYNARR_LINKAGE uint8_t DYNARR_FUNC(resize)(DYNARR_NAME* arr, size_t ncount) {
|
||||||
|
if (ncount < arr->count) return 1; // the new count is less than the current count, this is very likely unintentional
|
||||||
|
if (ncount == arr->cap) return 0; // the current capacity has already been set to this
|
||||||
|
|
||||||
|
// calculates what the new size should be by adding the amount of items to the count
|
||||||
|
// assumes scaling factor is 2
|
||||||
|
return DYNARR_FUNC(resize_exact)(arr, 1 << (size_t)ceil(log2(ncount)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// adds an item to the dynamic array, doubles the capacity if the new count exceeds the maximum
|
// adds an item to the dynamic array, doubles the capacity if the new count exceeds the maximum
|
||||||
// returns 0 upon success, 1 upon failure
|
// returns 0 upon success, 1 upon failure
|
||||||
DYNARR_LINKAGE uint8_t DYNARR_add(DYNARR_NAME* arr, DYNARR_TYPE item) {
|
DYNARR_LINKAGE uint8_t DYNARR_FUNC(add)(DYNARR_NAME* arr, DYNARR_TYPE item) {
|
||||||
size_t idx = arr->count;
|
size_t idx = arr->count;
|
||||||
arr->count++;
|
arr->count++;
|
||||||
|
|
||||||
// resize the dynamic array if the new count has hit the max capacity
|
// resize the dynamic array if the new count has hit the max capacity
|
||||||
if (arr->cap == arr->count) {
|
if (arr->cap == arr->count) {
|
||||||
if (!arr->cap) arr->cap = 1; // set the capacity to 1 if it's 0
|
uint8_t const s = !arr->cap // if zero
|
||||||
else arr->cap *= 2; // otherwise, multiply the capacity by 2
|
? DYNARR_FUNC(resize_exact)(arr, 1) // set the capacity to 1 if it's 0
|
||||||
DYNARR_TYPE* nptr = realloc(arr->dat, arr->cap * sizeof(DYNARR_TYPE));
|
: DYNARR_FUNC(resize_exact)(arr, arr->cap * 2); // otherwise, multiply the capacity by 2
|
||||||
|
// return 1 upon non-zero
|
||||||
if (nptr == NULL)
|
if (s) return 1;
|
||||||
return 1;
|
|
||||||
|
|
||||||
arr->dat = nptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
arr->dat[idx] = item;
|
arr->dat[idx] = item;
|
||||||
@@ -70,7 +88,7 @@ DYNARR_LINKAGE uint8_t DYNARR_add(DYNARR_NAME* arr, DYNARR_TYPE item) {
|
|||||||
|
|
||||||
// removes an item from the dynamic array from a certain index
|
// removes an item from the dynamic array from a certain index
|
||||||
// returns 0 upon success, 1 upon failure
|
// returns 0 upon success, 1 upon failure
|
||||||
DYNARR_LINKAGE uint8_t DYNARR_remove(DYNARR_NAME* arr, size_t idx) {
|
DYNARR_LINKAGE uint8_t DYNARR_FUNC(remove)(DYNARR_NAME* arr, size_t idx) {
|
||||||
if (arr->count == 0 || idx >= arr->count) return 1;
|
if (arr->count == 0 || idx >= arr->count) return 1;
|
||||||
|
|
||||||
// remove one from the count
|
// remove one from the count
|
||||||
@@ -85,17 +103,21 @@ DYNARR_LINKAGE uint8_t DYNARR_remove(DYNARR_NAME* arr, size_t idx) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// trims the parts of the dynamic array that isn't in use
|
||||||
|
DYNARR_LINKAGE uint8_t DYNARR_FUNC(trim)(DYNARR_NAME* arr) {
|
||||||
|
if (arr->cap == arr->count) return 0; // return success if no work needs to be done
|
||||||
|
return DYNARR_FUNC(resize_exact)(arr, arr->count);
|
||||||
|
}
|
||||||
|
|
||||||
// cleans up the resources associated with the array, do not use after this step. This is undefined behaviour
|
// cleans up the resources associated with the array, do not use after this step. This is undefined behaviour
|
||||||
DYNARR_LINKAGE void DYNARR_free(DYNARR_NAME* arr) {
|
DYNARR_LINKAGE void DYNARR_FUNC(free)(DYNARR_NAME* arr) {
|
||||||
|
if (arr->dat == NULL) return;
|
||||||
free(arr->dat);
|
free(arr->dat);
|
||||||
arr->dat = NULL;
|
*arr = (DYNARR_NAME){0}; // zero out all fields to re-initialize
|
||||||
}
|
}
|
||||||
|
|
||||||
// clean up all defined definitions so they can be used again later
|
// clean up all defined definitions so they can be used again later
|
||||||
#undef DYNARR_init
|
#undef DYNARR_FUNC
|
||||||
#undef DYNARR_add
|
|
||||||
#undef DYNARR_remove
|
|
||||||
#undef DYNARR_free
|
|
||||||
#undef DYNARR_NAME
|
#undef DYNARR_NAME
|
||||||
#undef DYNARR_LINKAGE
|
#undef DYNARR_LINKAGE
|
||||||
#undef DYNARR_TYPE
|
#undef DYNARR_TYPE
|
||||||
|
|||||||
Reference in New Issue
Block a user