This commit is contained in:
Richard Gill 2024-03-19 01:10:47 -03:00 committed by GitHub
commit 553d9134e7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 28 additions and 22 deletions

View File

@ -48,8 +48,8 @@ COMPILE-TIME OPTIONS
By default stb_ds uses stdlib realloc() and free() for memory management. You can
substitute your own functions instead by defining these symbols. You must either
define both, or neither. Note that at the moment, 'context' will always be NULL.
@TODO add an array/hash initialization function that takes a memory context pointer.
define both, or neither. To forward 'context' to those functions, call stbds_arrctx().
@TODO add an hash initialization function that takes a memory context pointer.
#define STBDS_UNIT_TESTS
@ -371,6 +371,7 @@ CREDITS
Per Vognsen -- idea for hash table API/implementation
Rafael Sachetto -- arrpop()
github:HeroicKatora -- arraddn() reworking
github:riri -- arrctx() context for custom realloc/free
Bugfixes:
Andy Durdin
@ -413,6 +414,7 @@ CREDITS
#define arrdelswap stbds_arrdelswap
#define arrcap stbds_arrcap
#define arrsetcap stbds_arrsetcap
#define arrctx stbds_arrctx
#define hmput stbds_hmput
#define hmputs stbds_hmputs
@ -491,7 +493,7 @@ extern void stbds_unit_tests(void);
// Everything below here is implementation details
//
extern void * stbds_arrgrowf(void *a, size_t elemsize, size_t addlen, size_t min_cap);
extern void * stbds_arrgrowf(void *a, size_t elemsize, size_t addlen, size_t min_cap, void *ctx);
extern void stbds_arrfreef(void *a);
extern void stbds_hmfree_func(void *p, size_t elemsize);
extern void * stbds_hmget_key(void *a, size_t elemsize, void *key, size_t keysize, int mode);
@ -534,31 +536,33 @@ extern void * stbds_shmode_func(size_t elemsize, int mode);
#define stbds_header(t) ((stbds_array_header *) (t) - 1)
#define stbds_temp(t) stbds_header(t)->temp
#define stbds_temp_key(t) (*(char **) stbds_header(t)->hash_table)
#define stbds_context(t) ((t) ? stbds_header(t)->context : NULL)
#define stbds_arrsetcap(a,n) (stbds_arrgrow(a,0,n))
#define stbds_arrsetcap(a,n) (stbds_arrgrow(a,0,n,stbds_context(a)))
#define stbds_arrsetlen(a,n) ((stbds_arrcap(a) < (size_t) (n) ? stbds_arrsetcap((a),(size_t)(n)),0 : 0), (a) ? stbds_header(a)->length = (size_t) (n) : 0)
#define stbds_arrcap(a) ((a) ? stbds_header(a)->capacity : 0)
#define stbds_arrlen(a) ((a) ? (ptrdiff_t) stbds_header(a)->length : 0)
#define stbds_arrlenu(a) ((a) ? stbds_header(a)->length : 0)
#define stbds_arrput(a,v) (stbds_arrmaybegrow(a,1), (a)[stbds_header(a)->length++] = (v))
#define stbds_arrput(a,v) (stbds_arrmaybegrow(a,1,stbds_context(a)), (a)[stbds_header(a)->length++] = (v))
#define stbds_arrpush stbds_arrput // synonym
#define stbds_arrpop(a) (stbds_header(a)->length--, (a)[stbds_header(a)->length])
#define stbds_arraddn(a,n) ((void)(stbds_arraddnindex(a, n))) // deprecated, use one of the following instead:
#define stbds_arraddnptr(a,n) (stbds_arrmaybegrow(a,n), (n) ? (stbds_header(a)->length += (n), &(a)[stbds_header(a)->length-(n)]) : (a))
#define stbds_arraddnindex(a,n)(stbds_arrmaybegrow(a,n), (n) ? (stbds_header(a)->length += (n), stbds_header(a)->length-(n)) : stbds_arrlen(a))
#define stbds_arraddnptr(a,n) (stbds_arrmaybegrow(a,n,stbds_context(a)), (n) ? (stbds_header(a)->length += (n), &(a)[stbds_header(a)->length-(n)]) : (a))
#define stbds_arraddnindex(a,n)(stbds_arrmaybegrow(a,n,stbds_context(a)), (n) ? (stbds_header(a)->length += (n), stbds_header(a)->length-(n)) : stbds_arrlen(a))
#define stbds_arraddnoff stbds_arraddnindex
#define stbds_arrlast(a) ((a)[stbds_header(a)->length-1])
#define stbds_arrfree(a) ((void) ((a) ? STBDS_FREE(NULL,stbds_header(a)) : (void)0), (a)=NULL)
#define stbds_arrfree(a) ((void) ((a) ? stbds_arrfreef(a) : (void)0), (a)=NULL)
#define stbds_arrdel(a,i) stbds_arrdeln(a,i,1)
#define stbds_arrdeln(a,i,n) (memmove(&(a)[i], &(a)[(i)+(n)], sizeof *(a) * (stbds_header(a)->length-(n)-(i))), stbds_header(a)->length -= (n))
#define stbds_arrdelswap(a,i) ((a)[i] = stbds_arrlast(a), stbds_header(a)->length -= 1)
#define stbds_arrinsn(a,i,n) (stbds_arraddn((a),(n)), memmove(&(a)[(i)+(n)], &(a)[i], sizeof *(a) * (stbds_header(a)->length-(n)-(i))))
#define stbds_arrins(a,i,v) (stbds_arrinsn((a),(i),1), (a)[i]=(v))
#define stbds_arrctx(a,c) (stbds_arrmaybegrow(a,0,c), stbds_header(a)->context = (c), (a))
#define stbds_arrmaybegrow(a,n) ((!(a) || stbds_header(a)->length + (n) > stbds_header(a)->capacity) \
? (stbds_arrgrow(a,n,0),0) : 0)
#define stbds_arrmaybegrow(a,n,x) ((!(a) || stbds_header(a)->length + (n) > stbds_header(a)->capacity) \
? (stbds_arrgrow(a,n,0,x),0) : 0)
#define stbds_arrgrow(a,b,c) ((a) = stbds_arrgrowf_wrapper((a), sizeof *(a), (b), (c)))
#define stbds_arrgrow(a,b,c,x) ((a) = stbds_arrgrowf_wrapper((a), sizeof *(a), (b), (c), (x)))
#define stbds_hmput(t, k, v) \
((t) = stbds_hmput_key_wrapper((t), sizeof *(t), (void*) STBDS_ADDRESSOF((t)->key, (k)), sizeof (t)->key, 0), \
@ -660,6 +664,7 @@ typedef struct
size_t capacity;
void * hash_table;
ptrdiff_t temp;
void * context;
} stbds_array_header;
typedef struct stbds_string_block
@ -690,8 +695,8 @@ enum
#ifdef __cplusplus
// in C we use implicit assignment from these void*-returning functions to T*.
// in C++ these templates make the same code work
template<class T> static T * stbds_arrgrowf_wrapper(T *a, size_t elemsize, size_t addlen, size_t min_cap) {
return (T*)stbds_arrgrowf((void *)a, elemsize, addlen, min_cap);
template<class T> static T * stbds_arrgrowf_wrapper(T *a, size_t elemsize, size_t addlen, size_t min_cap, void *ctx) {
return (T*)stbds_arrgrowf((void *)a, elemsize, addlen, min_cap, ctx);
}
template<class T> static T * stbds_hmget_key_wrapper(T *a, size_t elemsize, void *key, size_t keysize, int mode) {
return (T*)stbds_hmget_key((void*)a, elemsize, key, keysize, mode);
@ -759,7 +764,7 @@ size_t stbds_rehash_items;
//int *prev_allocs[65536];
//int num_prev;
void *stbds_arrgrowf(void *a, size_t elemsize, size_t addlen, size_t min_cap)
void *stbds_arrgrowf(void *a, size_t elemsize, size_t addlen, size_t min_cap, void *ctx)
{
stbds_array_header temp={0}; // force debugging
void *b;
@ -770,7 +775,7 @@ void *stbds_arrgrowf(void *a, size_t elemsize, size_t addlen, size_t min_cap)
if (min_len > min_cap)
min_cap = min_len;
if (min_cap <= stbds_arrcap(a))
if (a && min_cap <= stbds_arrcap(a))
return a;
// increase needed capacity to guarantee O(1) amortized
@ -782,13 +787,14 @@ void *stbds_arrgrowf(void *a, size_t elemsize, size_t addlen, size_t min_cap)
//if (num_prev < 65536) if (a) prev_allocs[num_prev++] = (int *) ((char *) a+1);
//if (num_prev == 2201)
// num_prev = num_prev;
b = STBDS_REALLOC(NULL, (a) ? stbds_header(a) : 0, elemsize * min_cap + sizeof(stbds_array_header));
b = STBDS_REALLOC(ctx, (a) ? stbds_header(a) : 0, elemsize * min_cap + sizeof(stbds_array_header));
//if (num_prev < 65536) prev_allocs[num_prev++] = (int *) (char *) b;
b = (char *) b + sizeof(stbds_array_header);
if (a == NULL) {
stbds_header(b)->length = 0;
stbds_header(b)->hash_table = 0;
stbds_header(b)->temp = 0;
stbds_header(b)->context = ctx;
} else {
STBDS_STATS(++stbds_array_grow);
}
@ -799,7 +805,7 @@ void *stbds_arrgrowf(void *a, size_t elemsize, size_t addlen, size_t min_cap)
void stbds_arrfreef(void *a)
{
STBDS_FREE(NULL, stbds_header(a));
STBDS_FREE(stbds_context(a), stbds_header(a));
}
//
@ -1283,7 +1289,7 @@ void * stbds_hmget_key_ts(void *a, size_t elemsize, void *key, size_t keysize, p
size_t keyoffset = 0;
if (a == NULL) {
// make it non-empty so we can return a temp
a = stbds_arrgrowf(0, elemsize, 0, 1);
a = stbds_arrgrowf(0, elemsize, 0, 1, NULL);
stbds_header(a)->length += 1;
memset(a, 0, elemsize);
*temp = STBDS_INDEX_EMPTY;
@ -1324,7 +1330,7 @@ void * stbds_hmput_default(void *a, size_t elemsize)
// a has a hash table but no entries, because of shmode <- grow
// a has entries <- do nothing
if (a == NULL || stbds_header(STBDS_HASH_TO_ARR(a,elemsize))->length == 0) {
a = stbds_arrgrowf(a ? STBDS_HASH_TO_ARR(a,elemsize) : NULL, elemsize, 0, 1);
a = stbds_arrgrowf(a ? STBDS_HASH_TO_ARR(a,elemsize) : NULL, elemsize, 0, 1, NULL);
stbds_header(a)->length += 1;
memset(a, 0, elemsize);
a=STBDS_ARR_TO_HASH(a,elemsize);
@ -1341,7 +1347,7 @@ void *stbds_hmput_key(void *a, size_t elemsize, void *key, size_t keysize, int m
stbds_hash_index *table;
if (a == NULL) {
a = stbds_arrgrowf(0, elemsize, 0, 1);
a = stbds_arrgrowf(0, elemsize, 0, 1, NULL);
memset(a, 0, elemsize);
stbds_header(a)->length += 1;
// adjust a to point AFTER the default element
@ -1437,7 +1443,7 @@ void *stbds_hmput_key(void *a, size_t elemsize, void *key, size_t keysize, int m
ptrdiff_t i = (ptrdiff_t) stbds_arrlen(a);
// we want to do stbds_arraddn(1), but we can't use the macros since we don't have something of the right type
if ((size_t) i+1 > stbds_arrcap(a))
*(void **) &a = stbds_arrgrowf(a, elemsize, 1, 0);
*(void **) &a = stbds_arrgrowf(a, elemsize, 1, 0, NULL);
raw_a = STBDS_ARR_TO_HASH(a,elemsize);
STBDS_ASSERT((size_t) i+1 <= stbds_arrcap(a));
@ -1460,7 +1466,7 @@ void *stbds_hmput_key(void *a, size_t elemsize, void *key, size_t keysize, int m
void * stbds_shmode_func(size_t elemsize, int mode)
{
void *a = stbds_arrgrowf(0, elemsize, 0, 1);
void *a = stbds_arrgrowf(0, elemsize, 0, 1, NULL);
stbds_hash_index *h;
memset(a, 0, elemsize);
stbds_header(a)->length = 1;