mirror of
https://github.com/thepigeongenerator/sdl_template.git
synced 2025-12-17 05:55:47 +01:00
apply some fixes to dynarr
This commit is contained in:
@@ -36,16 +36,15 @@ 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;
|
||||||
|
|
||||||
// adds an exact number of items to the capacity, does not respect scaling
|
// sets the capacity exactly, does not respect capacity scaling use `resize` if capacity scaling must be respected
|
||||||
// returns 0 upon success, 1 upon failure
|
// returns 0 upon success, 1 upon failure
|
||||||
DYNARR_LINKAGE uint8_t DYNARR_FUNC(resize_exact)(DYNARR_NAME* arr, size_t ncap) {
|
DYNARR_LINKAGE uint8_t DYNARR_FUNC(resize_exact)(DYNARR_NAME* arr, size_t ncap) {
|
||||||
|
if (ncap == 0) return 1; // cannot set the new capacity to zero
|
||||||
if (ncap < arr->count) return 1; // the new capacity is smaller than the count, this is very likely unintentional
|
if (ncap < arr->count) return 1; // the new capacity is smaller than the count, this is very likely unintentional
|
||||||
if (ncap == arr->cap) return 0; // the capacity is already the new capacity; no work needs to be done
|
if (ncap == arr->cap) return 0; // the capacity is already the new capacity; no work needs to be done
|
||||||
|
|
||||||
// (re)allocate the memory for the array
|
// (re)allocate the memory for the array
|
||||||
DYNARR_TYPE* nptr = (arr->dat == NULL)
|
DYNARR_TYPE* nptr = realloc(arr->dat, ncap * sizeof(DYNARR_TYPE)); // if dat is NULL, behaviour is equivalent to "malloc"
|
||||||
? malloc(ncap * sizeof(DYNARR_TYPE))
|
|
||||||
: realloc(arr->dat, ncap * sizeof(DYNARR_TYPE));
|
|
||||||
|
|
||||||
// if memory (re)allocation failed; return
|
// if memory (re)allocation failed; return
|
||||||
if (nptr == NULL)
|
if (nptr == NULL)
|
||||||
@@ -56,15 +55,16 @@ DYNARR_LINKAGE uint8_t DYNARR_FUNC(resize_exact)(DYNARR_NAME* arr, size_t ncap)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// resizes the array by adding `nitems` to the count, respects capacity scaling
|
// resizes the capacity, respects capacity scaling, use `resize_exact` if this behaviour isn't desirable (often it is)
|
||||||
// returns 0 upon success, 1 upon failure
|
// returns 0 upon success, 1 upon failure
|
||||||
DYNARR_LINKAGE uint8_t DYNARR_FUNC(resize)(DYNARR_NAME* arr, size_t ncount) {
|
DYNARR_LINKAGE uint8_t DYNARR_FUNC(resize)(DYNARR_NAME* arr, size_t ncap) {
|
||||||
if (ncount < arr->count) return 1; // the new count is less than the current count, this is very likely unintentional
|
if (ncap == 0) return 1; // cannot set the new capacity to zero
|
||||||
if (ncount == arr->cap) return 0; // the current capacity has already been set to this
|
if (ncap < arr->count) return 1; // the new count is less than the current count, this is very likely unintentional
|
||||||
|
if (ncap == 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
|
// calculates what the new size should be by adding the amount of items to the count
|
||||||
// assumes scaling factor is 2
|
// assumes scaling factor is 2
|
||||||
return DYNARR_FUNC(resize_exact)(arr, 1 << (size_t)ceil(log2(ncount)));
|
return DYNARR_FUNC(resize_exact)(arr, 1 << (size_t)ceil(log2(ncap)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
@@ -74,8 +74,12 @@ DYNARR_LINKAGE uint8_t DYNARR_FUNC(add)(DYNARR_NAME* arr, DYNARR_TYPE item) {
|
|||||||
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) {
|
||||||
uint8_t const s = !arr->cap // if zero
|
// fail if the capacity will overflow
|
||||||
|
if ((SIZE_MAX - arr->cap) < arr->cap) return 1;
|
||||||
|
|
||||||
|
// resize the capacity, store the status in s
|
||||||
|
uint8_t const s = !arr->cap
|
||||||
? DYNARR_FUNC(resize_exact)(arr, 1) // set the capacity to 1 if it's 0
|
? DYNARR_FUNC(resize_exact)(arr, 1) // set the capacity to 1 if it's 0
|
||||||
: DYNARR_FUNC(resize_exact)(arr, arr->cap * 2); // otherwise, multiply the capacity by 2
|
: DYNARR_FUNC(resize_exact)(arr, arr->cap * 2); // otherwise, multiply the capacity by 2
|
||||||
// return 1 upon non-zero
|
// return 1 upon non-zero
|
||||||
@@ -111,8 +115,7 @@ DYNARR_LINKAGE uint8_t DYNARR_FUNC(trim)(DYNARR_NAME* arr) {
|
|||||||
|
|
||||||
// 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_FUNC(free)(DYNARR_NAME* arr) {
|
DYNARR_LINKAGE void DYNARR_FUNC(free)(DYNARR_NAME* arr) {
|
||||||
if (arr->dat == NULL) return;
|
free(arr->dat); // free(NULL) is allowed
|
||||||
free(arr->dat);
|
|
||||||
*arr = (DYNARR_NAME){0}; // zero out all fields to re-initialize
|
*arr = (DYNARR_NAME){0}; // zero out all fields to re-initialize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user