mirror of
https://github.com/nothings/stb
synced 2025-04-02 07:52:57 +03:00
Merge 4063864f1defbae8db40b037fbc55ff59aa1b62f into 5c205738c191bcb0abc65c4febfa9bd25ff35234
This commit is contained in:
commit
a6e4121930
50
stb_ds.h
50
stb_ds.h
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user