stb_ds.h: thread-safe functions; pointer-returning functions; change return value of arraddn
This commit is contained in:
parent
aa482fc4a1
commit
d693c6103a
207
stb_ds.h
207
stb_ds.h
@ -1,4 +1,5 @@
|
|||||||
/* stb_ds.h - v0.62 - public domain data structures - Sean Barrett 2019
|
#include <stdio.h>
|
||||||
|
/* stb_ds.h - v0.62b - public domain data structures - Sean Barrett 2019
|
||||||
|
|
||||||
This is a single-header-file library that provides easy-to-use
|
This is a single-header-file library that provides easy-to-use
|
||||||
dynamic arrays and hash tables for C (also works in C++).
|
dynamic arrays and hash tables for C (also works in C++).
|
||||||
@ -108,6 +109,11 @@ DOCUMENTATION
|
|||||||
Inserts n uninitialized items into array a starting at a[p],
|
Inserts n uninitialized items into array a starting at a[p],
|
||||||
moving the rest of the array over.
|
moving the rest of the array over.
|
||||||
|
|
||||||
|
arraddn:
|
||||||
|
T* arraddn(T* a, int n)
|
||||||
|
Appends n uninitialized items onto array at the end.
|
||||||
|
Returns a pointer to the first uninitialized item added.
|
||||||
|
|
||||||
arrdel:
|
arrdel:
|
||||||
void arrdel(T* a, int p);
|
void arrdel(T* a, int p);
|
||||||
Deletes the element at a[p], moving the rest of the array over.
|
Deletes the element at a[p], moving the rest of the array over.
|
||||||
@ -191,15 +197,19 @@ DOCUMENTATION
|
|||||||
|
|
||||||
hmgeti
|
hmgeti
|
||||||
shgeti
|
shgeti
|
||||||
|
hmgeti_ts
|
||||||
ptrdiff_t hmgeti(T*, TK key)
|
ptrdiff_t hmgeti(T*, TK key)
|
||||||
ptrdiff_t shgeti(T*, char* key)
|
ptrdiff_t shgeti(T*, char* key)
|
||||||
|
ptrdiff_t hmgeti_ts(T*, TK key, ptrdiff_t tempvar)
|
||||||
Returns the index in the hashmap which has the key 'key', or -1
|
Returns the index in the hashmap which has the key 'key', or -1
|
||||||
if the key is not present.
|
if the key is not present.
|
||||||
|
|
||||||
hmget
|
hmget
|
||||||
|
hmget_ts
|
||||||
shget
|
shget
|
||||||
TV hmget(T*, TK key)
|
TV hmget(T*, TK key)
|
||||||
TV shget(T*, char* key)
|
TV shget(T*, char* key)
|
||||||
|
TV hmget_ts(T*, TK key, ptrdiff_t tempvar)
|
||||||
Returns the value corresponding to 'key' in the hashmap.
|
Returns the value corresponding to 'key' in the hashmap.
|
||||||
The structure must have a 'value' field
|
The structure must have a 'value' field
|
||||||
|
|
||||||
@ -209,6 +219,21 @@ DOCUMENTATION
|
|||||||
T shgets(T*, char* key)
|
T shgets(T*, char* key)
|
||||||
Returns the structure corresponding to 'key' in the hashmap.
|
Returns the structure corresponding to 'key' in the hashmap.
|
||||||
|
|
||||||
|
hmgetp
|
||||||
|
shgetp
|
||||||
|
hmgetp_ts
|
||||||
|
hmgetp_null
|
||||||
|
shgetp_null
|
||||||
|
T* hmgetp(T*, TK key)
|
||||||
|
T* shgetp(T*, char* key)
|
||||||
|
T* hmgetp_ts(T*, TK key, ptrdiff_t tempvar)
|
||||||
|
T* hmgetp_null(T*, TK key)
|
||||||
|
T* shgetp_null(T*, char *key)
|
||||||
|
Returns a pointer to the structure corresponding to 'key' in
|
||||||
|
the hashmap. Functions ending in "_null" return NULL if the key
|
||||||
|
is not present in the hashmap; the others return a pointer to a
|
||||||
|
structure holding the default value (but not the searched-for key).
|
||||||
|
|
||||||
hmdefault
|
hmdefault
|
||||||
shdefault
|
shdefault
|
||||||
TV hmdefault(T*, TV value)
|
TV hmdefault(T*, TV value)
|
||||||
@ -234,7 +259,7 @@ DOCUMENTATION
|
|||||||
shputs
|
shputs
|
||||||
T hmputs(T*, T item)
|
T hmputs(T*, T item)
|
||||||
T shputs(T*, T item)
|
T shputs(T*, T item)
|
||||||
Inserts a struct with T.key and T.value into the hashmap. If the struct is already
|
Inserts a struct with T.key into the hashmap. If the struct is already
|
||||||
present in the hashmap, updates it.
|
present in the hashmap, updates it.
|
||||||
|
|
||||||
hmdel
|
hmdel
|
||||||
@ -263,12 +288,22 @@ DOCUMENTATION
|
|||||||
|
|
||||||
NOTES
|
NOTES
|
||||||
|
|
||||||
* These data structures are realloc'd when they grow, and the macro "functions"
|
* These data structures are realloc'd when they grow, and the macro
|
||||||
write to the provided pointer. This means: (a) the pointer must be an lvalue,
|
"functions" write to the provided pointer. This means: (a) the pointer
|
||||||
and (b) the pointer to the data structure is not stable, and you must maintain
|
must be an lvalue, and (b) the pointer to the data structure is not
|
||||||
it the same as you would a realloc'd pointer. For example, if you pass a pointer
|
stable, and you must maintain it the same as you would a realloc'd
|
||||||
to a dynamic array to a function which updates it, the function must return
|
pointer. For example, if you pass a pointer to a dynamic array to a
|
||||||
back the new pointer to the caller. This is the price of trying to do this in C.
|
function which updates it, the function must return back the new
|
||||||
|
pointer to the caller. This is the price of trying to do this in C.
|
||||||
|
|
||||||
|
* The following are the only functions that are thread-safe on a single data
|
||||||
|
structure, i.e. can be run in multiple threads simultaneously on the same
|
||||||
|
data structure
|
||||||
|
hmlen shlen
|
||||||
|
hmlenu shlenu
|
||||||
|
hmget_ts shget_ts
|
||||||
|
hmgeti_ts shgeti_ts
|
||||||
|
hmgets_ts shgets_ts
|
||||||
|
|
||||||
* You iterate over the contents of a dynamic array and a hashmap in exactly
|
* You iterate over the contents of a dynamic array and a hashmap in exactly
|
||||||
the same way, using arrlen/hmlen/shlen:
|
the same way, using arrlen/hmlen/shlen:
|
||||||
@ -298,7 +333,8 @@ NOTES - HASH MAP
|
|||||||
* For compilers other than GCC and clang (e.g. Visual Studio), for hmput/hmget/hmdel
|
* For compilers other than GCC and clang (e.g. Visual Studio), for hmput/hmget/hmdel
|
||||||
and variants, the key must be an lvalue (so the macro can take the address of it).
|
and variants, the key must be an lvalue (so the macro can take the address of it).
|
||||||
Extensions are used that eliminate this requirement if you're using C99 and later
|
Extensions are used that eliminate this requirement if you're using C99 and later
|
||||||
in GCC or clang, or if you're using C++ in GCC.
|
in GCC or clang, or if you're using C++ in GCC. But note that this can make your
|
||||||
|
code less portable.
|
||||||
|
|
||||||
* To test for presence of a key in a hashmap, just do 'hmgeti(foo,key) >= 0'.
|
* To test for presence of a key in a hashmap, just do 'hmgeti(foo,key) >= 0'.
|
||||||
|
|
||||||
@ -368,9 +404,13 @@ CREDITS
|
|||||||
#define hmput stbds_hmput
|
#define hmput stbds_hmput
|
||||||
#define hmputs stbds_hmputs
|
#define hmputs stbds_hmputs
|
||||||
#define hmget stbds_hmget
|
#define hmget stbds_hmget
|
||||||
|
#define hmget_ts stbds_hmget_ts
|
||||||
#define hmgets stbds_hmgets
|
#define hmgets stbds_hmgets
|
||||||
#define hmgetp stbds_hmgetp
|
#define hmgetp stbds_hmgetp
|
||||||
|
#define hmgetp_ts stbds_hmgetp_ts
|
||||||
|
#define hmgetp_null stbds_hmgetp_null
|
||||||
#define hmgeti stbds_hmgeti
|
#define hmgeti stbds_hmgeti
|
||||||
|
#define hmgeti_ts stbds_hmgeti_ts
|
||||||
#define hmdel stbds_hmdel
|
#define hmdel stbds_hmdel
|
||||||
#define hmlen stbds_hmlen
|
#define hmlen stbds_hmlen
|
||||||
#define hmlenu stbds_hmlenu
|
#define hmlenu stbds_hmlenu
|
||||||
@ -379,11 +419,13 @@ CREDITS
|
|||||||
#define hmdefaults stbds_hmdefaults
|
#define hmdefaults stbds_hmdefaults
|
||||||
|
|
||||||
#define shput stbds_shput
|
#define shput stbds_shput
|
||||||
|
#define shputi stbds_shputi
|
||||||
#define shputs stbds_shputs
|
#define shputs stbds_shputs
|
||||||
#define shget stbds_shget
|
#define shget stbds_shget
|
||||||
|
#define shgeti stbds_shgeti
|
||||||
#define shgets stbds_shgets
|
#define shgets stbds_shgets
|
||||||
#define shgetp stbds_shgetp
|
#define shgetp stbds_shgetp
|
||||||
#define shgeti stbds_shgeti
|
#define shgetp_null stbds_shgetp_null
|
||||||
#define shdel stbds_shdel
|
#define shdel stbds_shdel
|
||||||
#define shlen stbds_shlen
|
#define shlen stbds_shlen
|
||||||
#define shlenu stbds_shlenu
|
#define shlenu stbds_shlenu
|
||||||
@ -431,8 +473,9 @@ extern void stbds_unit_tests(void);
|
|||||||
//
|
//
|
||||||
|
|
||||||
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);
|
||||||
extern void stbds_hmfree_func(void *p, size_t elemsize, size_t keyoff);
|
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);
|
extern void * stbds_hmget_key(void *a, size_t elemsize, void *key, size_t keysize, int mode);
|
||||||
|
extern void * stbds_hmget_key_ts(void *a, size_t elemsize, void *key, size_t keysize, ptrdiff_t *temp, int mode);
|
||||||
extern void * stbds_hmput_default(void *a, size_t elemsize);
|
extern void * stbds_hmput_default(void *a, size_t elemsize);
|
||||||
extern void * stbds_hmput_key(void *a, size_t elemsize, void *key, size_t keysize, int mode);
|
extern void * stbds_hmput_key(void *a, size_t elemsize, void *key, size_t keysize, int mode);
|
||||||
extern void * stbds_hmdel_key(void *a, size_t elemsize, void *key, size_t keysize, size_t keyoffset, int mode);
|
extern void * stbds_hmdel_key(void *a, size_t elemsize, void *key, size_t keysize, size_t keyoffset, int mode);
|
||||||
@ -472,14 +515,14 @@ extern void * stbds_shmode_func(size_t elemsize, int mode);
|
|||||||
#define stbds_temp(t) stbds_header(t)->temp
|
#define stbds_temp(t) stbds_header(t)->temp
|
||||||
|
|
||||||
#define stbds_arrsetcap(a,n) (stbds_arrgrow(a,0,n))
|
#define stbds_arrsetcap(a,n) (stbds_arrgrow(a,0,n))
|
||||||
#define stbds_arrsetlen(a,n) ((stbds_arrcap(a) < n ? stbds_arrsetcap(a,n),0 : 0), (a) ? stbds_header(a)->length = (n) : 0)
|
#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_arrcap(a) ((a) ? stbds_header(a)->capacity : 0)
|
||||||
#define stbds_arrlen(a) ((a) ? (ptrdiff_t) stbds_header(a)->length : 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_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), (a)[stbds_header(a)->length++] = (v))
|
||||||
#define stbds_arrpush stbds_arrput // synonym
|
#define stbds_arrpush stbds_arrput // synonym
|
||||||
#define stbds_arrpop(a) (stbds_header(a)->length--, (a)[stbds_header(a)->length])
|
#define stbds_arrpop(a) (stbds_header(a)->length--, (a)[stbds_header(a)->length])
|
||||||
#define stbds_arraddn(a,n) (stbds_arrmaybegrow(a,n), stbds_header(a)->length += (n))
|
#define stbds_arraddn(a,n) (stbds_arrmaybegrow(a,n), stbds_header(a)->length += (n), stbds_header(a)->length-(n))
|
||||||
#define stbds_arrlast(a) ((a)[stbds_header(a)->length-1])
|
#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_FREE(NULL,stbds_header(a)) : (void)0), (a)=NULL)
|
||||||
#define stbds_arrdel(a,i) stbds_arrdeln(a,i,1)
|
#define stbds_arrdel(a,i) stbds_arrdeln(a,i,1)
|
||||||
@ -506,9 +549,16 @@ extern void * stbds_shmode_func(size_t elemsize, int mode);
|
|||||||
((t) = stbds_hmget_key_wrapper((t), sizeof *(t), (void*) STBDS_ADDRESSOF((t)->key, (k)), sizeof (t)->key, STBDS_HM_BINARY), \
|
((t) = stbds_hmget_key_wrapper((t), sizeof *(t), (void*) STBDS_ADDRESSOF((t)->key, (k)), sizeof (t)->key, STBDS_HM_BINARY), \
|
||||||
stbds_temp((t)-1))
|
stbds_temp((t)-1))
|
||||||
|
|
||||||
|
#define stbds_hmgeti_ts(t,k,temp) \
|
||||||
|
((t) = stbds_hmget_key_ts_wrapper((t), sizeof *(t), (void*) STBDS_ADDRESSOF((t)->key, (k)), sizeof (t)->key, &(temp), STBDS_HM_BINARY), \
|
||||||
|
(temp))
|
||||||
|
|
||||||
#define stbds_hmgetp(t, k) \
|
#define stbds_hmgetp(t, k) \
|
||||||
((void) stbds_hmgeti(t,k), &(t)[stbds_temp((t)-1)])
|
((void) stbds_hmgeti(t,k), &(t)[stbds_temp((t)-1)])
|
||||||
|
|
||||||
|
#define stbds_hmgetp_ts(t, k, temp) \
|
||||||
|
((void) stbds_hmgeti_ts(t,k,temp), &(t)[temp])
|
||||||
|
|
||||||
#define stbds_hmdel(t,k) \
|
#define stbds_hmdel(t,k) \
|
||||||
(((t) = stbds_hmdel_key_wrapper((t),sizeof *(t), (void*) STBDS_ADDRESSOF((t)->key, (k)), sizeof (t)->key, STBDS_OFFSETOF((t),key), STBDS_HM_BINARY)),(t)?stbds_temp((t)-1):0)
|
(((t) = stbds_hmdel_key_wrapper((t),sizeof *(t), (void*) STBDS_ADDRESSOF((t)->key, (k)), sizeof (t)->key, STBDS_OFFSETOF((t),key), STBDS_HM_BINARY)),(t)?stbds_temp((t)-1):0)
|
||||||
|
|
||||||
@ -519,30 +569,49 @@ extern void * stbds_shmode_func(size_t elemsize, int mode);
|
|||||||
((t) = stbds_hmput_default_wrapper((t), sizeof *(t)), (t)[-1] = (s))
|
((t) = stbds_hmput_default_wrapper((t), sizeof *(t)), (t)[-1] = (s))
|
||||||
|
|
||||||
#define stbds_hmfree(p) \
|
#define stbds_hmfree(p) \
|
||||||
((void) ((p) != NULL ? stbds_hmfree_func((p)-1,sizeof*(p),STBDS_OFFSETOF((p),key)),0 : 0),(p)=NULL)
|
((void) ((p) != NULL ? stbds_hmfree_func((p)-1,sizeof*(p)),0 : 0),(p)=NULL)
|
||||||
|
|
||||||
#define stbds_hmgets(t, k) (*stbds_hmgetp(t,k))
|
#define stbds_hmgets(t, k) (*stbds_hmgetp(t,k))
|
||||||
#define stbds_hmget(t, k) (stbds_hmgetp(t,k)->value)
|
#define stbds_hmget(t, k) (stbds_hmgetp(t,k)->value)
|
||||||
|
#define stbds_hmget_ts(t, k, temp) (stbds_hmgetp_ts(t,k,temp)->value)
|
||||||
#define stbds_hmlen(t) ((t) ? (ptrdiff_t) stbds_header((t)-1)->length-1 : 0)
|
#define stbds_hmlen(t) ((t) ? (ptrdiff_t) stbds_header((t)-1)->length-1 : 0)
|
||||||
#define stbds_hmlenu(t) ((t) ? stbds_header((t)-1)->length-1 : 0)
|
#define stbds_hmlenu(t) ((t) ? stbds_header((t)-1)->length-1 : 0)
|
||||||
|
#define stbds_hmgetp_null(t,k) (stbds_hmgeti(t,k) == -1 ? NULL : &(t)[stbds_temp(t)-1])
|
||||||
|
|
||||||
#define stbds_shput(t, k, v) \
|
#define stbds_shput(t, k, v) \
|
||||||
((t) = stbds_hmput_key_wrapper((t), sizeof *(t), (void*) (k), sizeof (t)->key, STBDS_HM_STRING), \
|
((t) = stbds_hmput_key_wrapper((t), sizeof *(t), (void*) (k), sizeof (t)->key, STBDS_HM_STRING), \
|
||||||
(t)[stbds_temp((t)-1)].value = (v))
|
(t)[stbds_temp((t)-1)].value = (v))
|
||||||
|
|
||||||
|
#define stbds_shputi(t, k, v) \
|
||||||
|
((t) = stbds_hmput_key_wrapper((t), sizeof *(t), (void*) (k), sizeof (t)->key, STBDS_HM_STRING), \
|
||||||
|
(t)[stbds_temp((t)-1)].value = (v), stbds_temp((t)-1))
|
||||||
|
|
||||||
#define stbds_shputs(t, s) \
|
#define stbds_shputs(t, s) \
|
||||||
((t) = stbds_hmput_key_wrapper((t), sizeof *(t), (void*) (s).key, sizeof (s).key, STBDS_HM_STRING), \
|
((t) = stbds_hmput_key_wrapper((t), sizeof *(t), (void*) (s).key, sizeof (s).key, STBDS_HM_STRING), \
|
||||||
(t)[stbds_temp((t)-1)] = (s))
|
(t)[stbds_temp((t)-1)] = (s))
|
||||||
|
|
||||||
|
#define stbds_pshput(t, p) \
|
||||||
|
((t) = stbds_hmput_key_wrapper((t), sizeof *(t), (void*) (p)->key, sizeof (p)->key, STBDS_HM_PTR_TO_STRING), \
|
||||||
|
(t)[stbds_temp((t)-1)] = (p))
|
||||||
|
|
||||||
#define stbds_shgeti(t,k) \
|
#define stbds_shgeti(t,k) \
|
||||||
((t) = stbds_hmget_key_wrapper((t), sizeof *(t), (void*) (k), sizeof (t)->key, STBDS_HM_STRING), \
|
((t) = stbds_hmget_key_wrapper((t), sizeof *(t), (void*) (k), sizeof (t)->key, STBDS_HM_STRING), \
|
||||||
stbds_temp((t)-1))
|
stbds_temp((t)-1))
|
||||||
|
|
||||||
|
#define stbds_pshgeti(t,k) \
|
||||||
|
((t) = stbds_hmget_key_wrapper((t), sizeof *(t), (void*) (k), sizeof (*(t))->key, STBDS_HM_PTR_TO_STRING), \
|
||||||
|
stbds_temp((t)-1))
|
||||||
|
|
||||||
#define stbds_shgetp(t, k) \
|
#define stbds_shgetp(t, k) \
|
||||||
((void) stbds_shgeti(t,k), &(t)[stbds_temp((t)-1)])
|
((void) stbds_shgeti(t,k), &(t)[stbds_temp((t)-1)])
|
||||||
|
|
||||||
|
#define stbds_pshget(t, k) \
|
||||||
|
((void) stbds_pshgeti(t,k), (t)[stbds_temp((t)-1)])
|
||||||
|
|
||||||
#define stbds_shdel(t,k) \
|
#define stbds_shdel(t,k) \
|
||||||
(((t) = stbds_hmdel_key_wrapper((t),sizeof *(t), (void*) (k), sizeof (t)->key, STBDS_OFFSETOF((t),key), STBDS_HM_STRING)),(t)?stbds_temp((t)-1):0)
|
(((t) = stbds_hmdel_key_wrapper((t),sizeof *(t), (void*) (k), sizeof (t)->key, STBDS_OFFSETOF((t),key), STBDS_HM_STRING)),(t)?stbds_temp((t)-1):0)
|
||||||
|
#define stbds_pshdel(t,k) \
|
||||||
|
(((t) = stbds_hmdel_key_wrapper((t),sizeof *(t), (void*) (k), sizeof (*(t))->key, STBDS_OFFSETOF(*(t),key), STBDS_HM_PTR_TO_STRING)),(t)?stbds_temp((t)-1):0)
|
||||||
|
|
||||||
#define stbds_sh_new_arena(t) \
|
#define stbds_sh_new_arena(t) \
|
||||||
((t) = stbds_shmode_func_wrapper(t, sizeof *(t), STBDS_SH_ARENA))
|
((t) = stbds_shmode_func_wrapper(t, sizeof *(t), STBDS_SH_ARENA))
|
||||||
@ -557,6 +626,7 @@ extern void * stbds_shmode_func(size_t elemsize, int mode);
|
|||||||
|
|
||||||
#define stbds_shgets(t, k) (*stbds_shgetp(t,k))
|
#define stbds_shgets(t, k) (*stbds_shgetp(t,k))
|
||||||
#define stbds_shget(t, k) (stbds_shgetp(t,k)->value)
|
#define stbds_shget(t, k) (stbds_shgetp(t,k)->value)
|
||||||
|
#define stbds_shgetp_null(t,k) (stbds_shgeti(t,k) == -1 ? NULL : &(t)[stbds_temp(t)-1])
|
||||||
#define stbds_shlen stbds_hmlen
|
#define stbds_shlen stbds_hmlen
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -587,6 +657,7 @@ struct stbds_string_arena
|
|||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
STBDS_SH_NONE,
|
STBDS_SH_NONE,
|
||||||
|
STBDS_SH_DEFAULT,
|
||||||
STBDS_SH_STRDUP,
|
STBDS_SH_STRDUP,
|
||||||
STBDS_SH_ARENA
|
STBDS_SH_ARENA
|
||||||
};
|
};
|
||||||
@ -600,6 +671,9 @@ template<class T> static T * stbds_arrgrowf_wrapper(T *a, size_t elemsize, size_
|
|||||||
template<class T> static T * stbds_hmget_key_wrapper(T *a, size_t elemsize, void *key, size_t keysize, int mode) {
|
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);
|
return (T*)stbds_hmget_key((void*)a, elemsize, key, keysize, mode);
|
||||||
}
|
}
|
||||||
|
template<class T> static T * stbds_hmget_key_ts_wrapper(T *a, size_t elemsize, void *key, size_t keysize, ptrdiff_t *temp, int mode) {
|
||||||
|
return (T*)stbds_hmget_key((void*)a, elemsize, key, keysize, temp, mode);
|
||||||
|
}
|
||||||
template<class T> static T * stbds_hmput_default_wrapper(T *a, size_t elemsize) {
|
template<class T> static T * stbds_hmput_default_wrapper(T *a, size_t elemsize) {
|
||||||
return (T*)stbds_hmput_default((void *)a, elemsize);
|
return (T*)stbds_hmput_default((void *)a, elemsize);
|
||||||
}
|
}
|
||||||
@ -615,6 +689,7 @@ template<class T> static T * stbds_shmode_func_wrapper(T *, size_t elemsize, int
|
|||||||
#else
|
#else
|
||||||
#define stbds_arrgrowf_wrapper stbds_arrgrowf
|
#define stbds_arrgrowf_wrapper stbds_arrgrowf
|
||||||
#define stbds_hmget_key_wrapper stbds_hmget_key
|
#define stbds_hmget_key_wrapper stbds_hmget_key
|
||||||
|
#define stbds_hmget_key_ts_wrapper stbds_hmget_key_ts
|
||||||
#define stbds_hmput_default_wrapper stbds_hmput_default
|
#define stbds_hmput_default_wrapper stbds_hmput_default
|
||||||
#define stbds_hmput_key_wrapper stbds_hmput_key
|
#define stbds_hmput_key_wrapper stbds_hmput_key
|
||||||
#define stbds_hmdel_key_wrapper stbds_hmdel_key
|
#define stbds_hmdel_key_wrapper stbds_hmdel_key
|
||||||
@ -656,6 +731,9 @@ size_t stbds_rehash_items;
|
|||||||
// stbds_arr implementation
|
// stbds_arr implementation
|
||||||
//
|
//
|
||||||
|
|
||||||
|
//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 *b;
|
void *b;
|
||||||
@ -674,7 +752,11 @@ void *stbds_arrgrowf(void *a, size_t elemsize, size_t addlen, size_t min_cap)
|
|||||||
else if (min_cap < 4)
|
else if (min_cap < 4)
|
||||||
min_cap = 4;
|
min_cap = 4;
|
||||||
|
|
||||||
|
//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(NULL, (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);
|
b = (char *) b + sizeof(stbds_array_header);
|
||||||
if (a == NULL) {
|
if (a == NULL) {
|
||||||
stbds_header(b)->length = 0;
|
stbds_header(b)->length = 0;
|
||||||
@ -683,6 +765,7 @@ void *stbds_arrgrowf(void *a, size_t elemsize, size_t addlen, size_t min_cap)
|
|||||||
STBDS_STATS(++stbds_array_grow);
|
STBDS_STATS(++stbds_array_grow);
|
||||||
}
|
}
|
||||||
stbds_header(b)->capacity = min_cap;
|
stbds_header(b)->capacity = min_cap;
|
||||||
|
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -925,6 +1008,11 @@ typedef int STBDS_SIPHASH_2_4_can_only_be_used_in_64_bit_builds[sizeof(size_t) =
|
|||||||
#define STBDS_SIPHASH_D_ROUNDS 1
|
#define STBDS_SIPHASH_D_ROUNDS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable:4127) // conditional expression is constant, for do..while(0) and sizeof()==
|
||||||
|
#endif
|
||||||
|
|
||||||
static size_t stbds_siphash_bytes(void *p, size_t len, size_t seed)
|
static size_t stbds_siphash_bytes(void *p, size_t len, size_t seed)
|
||||||
{
|
{
|
||||||
unsigned char *d = (unsigned char *) p;
|
unsigned char *d = (unsigned char *) p;
|
||||||
@ -982,6 +1070,7 @@ static size_t stbds_siphash_bytes(void *p, size_t len, size_t seed)
|
|||||||
v2 ^= 0xff;
|
v2 ^= 0xff;
|
||||||
for (j=0; j < STBDS_SIPHASH_D_ROUNDS; ++j)
|
for (j=0; j < STBDS_SIPHASH_D_ROUNDS; ++j)
|
||||||
STBDS_SIPROUND();
|
STBDS_SIPROUND();
|
||||||
|
|
||||||
#ifdef STBDS_SIPHASH_2_4
|
#ifdef STBDS_SIPHASH_2_4
|
||||||
return v0^v1^v2^v3;
|
return v0^v1^v2^v3;
|
||||||
#else
|
#else
|
||||||
@ -1071,8 +1160,12 @@ size_t stbds_hash_bytes(void *p, size_t len, size_t seed)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
static int stbds_is_key_equal(void *a, size_t elemsize, void *key, size_t keysize, int mode, size_t i)
|
|
||||||
|
static int stbds_is_key_equal(void *a, size_t elemsize, void *key, size_t keysize, size_t keyoffset, int mode, size_t i)
|
||||||
{
|
{
|
||||||
if (mode >= STBDS_HM_STRING)
|
if (mode >= STBDS_HM_STRING)
|
||||||
return 0==strcmp((char *) key, * (char **) ((char *) a + elemsize*i));
|
return 0==strcmp((char *) key, * (char **) ((char *) a + elemsize*i));
|
||||||
@ -1085,7 +1178,7 @@ static int stbds_is_key_equal(void *a, size_t elemsize, void *key, size_t keysiz
|
|||||||
|
|
||||||
#define stbds_hash_table(a) ((stbds_hash_index *) stbds_header(a)->hash_table)
|
#define stbds_hash_table(a) ((stbds_hash_index *) stbds_header(a)->hash_table)
|
||||||
|
|
||||||
void stbds_hmfree_func(void *a, size_t elemsize, size_t keyoff)
|
void stbds_hmfree_func(void *a, size_t elemsize)
|
||||||
{
|
{
|
||||||
if (a == NULL) return;
|
if (a == NULL) return;
|
||||||
if (stbds_hash_table(a) != NULL) {
|
if (stbds_hash_table(a) != NULL) {
|
||||||
@ -1101,7 +1194,7 @@ void stbds_hmfree_func(void *a, size_t elemsize, size_t keyoff)
|
|||||||
STBDS_FREE(NULL, stbds_header(a));
|
STBDS_FREE(NULL, stbds_header(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
static ptrdiff_t stbds_hm_find_slot(void *a, size_t elemsize, void *key, size_t keysize, int mode)
|
static ptrdiff_t stbds_hm_find_slot(void *a, size_t elemsize, void *key, size_t keysize, size_t keyoffset, int mode)
|
||||||
{
|
{
|
||||||
void *raw_a = STBDS_HASH_TO_ARR(a,elemsize);
|
void *raw_a = STBDS_HASH_TO_ARR(a,elemsize);
|
||||||
stbds_hash_index *table = stbds_hash_table(raw_a);
|
stbds_hash_index *table = stbds_hash_table(raw_a);
|
||||||
@ -1122,7 +1215,7 @@ static ptrdiff_t stbds_hm_find_slot(void *a, size_t elemsize, void *key, size_t
|
|||||||
// start searching from pos to end of bucket, this should help performance on small hash tables that fit in cache
|
// start searching from pos to end of bucket, this should help performance on small hash tables that fit in cache
|
||||||
for (i=pos & STBDS_BUCKET_MASK; i < STBDS_BUCKET_LENGTH; ++i) {
|
for (i=pos & STBDS_BUCKET_MASK; i < STBDS_BUCKET_LENGTH; ++i) {
|
||||||
if (bucket->hash[i] == hash) {
|
if (bucket->hash[i] == hash) {
|
||||||
if (stbds_is_key_equal(a, elemsize, key, keysize, mode, bucket->index[i])) {
|
if (stbds_is_key_equal(a, elemsize, key, keysize, keyoffset, mode, bucket->index[i])) {
|
||||||
return (pos & ~STBDS_BUCKET_MASK)+i;
|
return (pos & ~STBDS_BUCKET_MASK)+i;
|
||||||
}
|
}
|
||||||
} else if (bucket->hash[i] == STBDS_HASH_EMPTY) {
|
} else if (bucket->hash[i] == STBDS_HASH_EMPTY) {
|
||||||
@ -1134,7 +1227,7 @@ static ptrdiff_t stbds_hm_find_slot(void *a, size_t elemsize, void *key, size_t
|
|||||||
limit = pos & STBDS_BUCKET_MASK;
|
limit = pos & STBDS_BUCKET_MASK;
|
||||||
for (i = 0; i < limit; ++i) {
|
for (i = 0; i < limit; ++i) {
|
||||||
if (bucket->hash[i] == hash) {
|
if (bucket->hash[i] == hash) {
|
||||||
if (stbds_is_key_equal(a, elemsize, key, keysize, mode, bucket->index[i])) {
|
if (stbds_is_key_equal(a, elemsize, key, keysize, keyoffset, mode, bucket->index[i])) {
|
||||||
return (pos & ~STBDS_BUCKET_MASK)+i;
|
return (pos & ~STBDS_BUCKET_MASK)+i;
|
||||||
}
|
}
|
||||||
} else if (bucket->hash[i] == STBDS_HASH_EMPTY) {
|
} else if (bucket->hash[i] == STBDS_HASH_EMPTY) {
|
||||||
@ -1148,17 +1241,17 @@ static ptrdiff_t stbds_hm_find_slot(void *a, size_t elemsize, void *key, size_t
|
|||||||
pos &= (table->slot_count-1);
|
pos &= (table->slot_count-1);
|
||||||
}
|
}
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void * stbds_hmget_key(void *a, size_t elemsize, void *key, size_t keysize, int mode)
|
void * stbds_hmget_key_ts(void *a, size_t elemsize, void *key, size_t keysize, ptrdiff_t *temp, int mode)
|
||||||
{
|
{
|
||||||
|
size_t keyoffset = 0;
|
||||||
if (a == NULL) {
|
if (a == NULL) {
|
||||||
// make it non-empty so we can return a temp
|
// make it non-empty so we can return a temp
|
||||||
a = stbds_arrgrowf(0, elemsize, 0, 1);
|
a = stbds_arrgrowf(0, elemsize, 0, 1);
|
||||||
stbds_header(a)->length += 1;
|
stbds_header(a)->length += 1;
|
||||||
memset(a, 0, elemsize);
|
memset(a, 0, elemsize);
|
||||||
stbds_temp(a) = STBDS_INDEX_EMPTY;
|
*temp = STBDS_INDEX_EMPTY;
|
||||||
// adjust a to point after the default element
|
// adjust a to point after the default element
|
||||||
return STBDS_ARR_TO_HASH(a,elemsize);
|
return STBDS_ARR_TO_HASH(a,elemsize);
|
||||||
} else {
|
} else {
|
||||||
@ -1167,20 +1260,28 @@ void * stbds_hmget_key(void *a, size_t elemsize, void *key, size_t keysize, int
|
|||||||
// adjust a to point to the default element
|
// adjust a to point to the default element
|
||||||
table = (stbds_hash_index *) stbds_header(raw_a)->hash_table;
|
table = (stbds_hash_index *) stbds_header(raw_a)->hash_table;
|
||||||
if (table == 0) {
|
if (table == 0) {
|
||||||
stbds_temp(raw_a) = -1;
|
*temp = -1;
|
||||||
} else {
|
} else {
|
||||||
ptrdiff_t slot = stbds_hm_find_slot(a, elemsize, key, keysize, mode);
|
ptrdiff_t slot = stbds_hm_find_slot(a, elemsize, key, keysize, keyoffset, mode);
|
||||||
if (slot < 0) {
|
if (slot < 0) {
|
||||||
stbds_temp(raw_a) = STBDS_INDEX_EMPTY;
|
*temp = STBDS_INDEX_EMPTY;
|
||||||
} else {
|
} else {
|
||||||
stbds_hash_bucket *b = &table->storage[slot >> STBDS_BUCKET_SHIFT];
|
stbds_hash_bucket *b = &table->storage[slot >> STBDS_BUCKET_SHIFT];
|
||||||
stbds_temp(raw_a) = b->index[slot & STBDS_BUCKET_MASK];
|
*temp = b->index[slot & STBDS_BUCKET_MASK];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void * stbds_hmget_key(void *a, size_t elemsize, void *key, size_t keysize, int mode)
|
||||||
|
{
|
||||||
|
ptrdiff_t temp;
|
||||||
|
void *p = stbds_hmget_key_ts(a, elemsize, key, keysize, &temp, mode);
|
||||||
|
stbds_temp(STBDS_HASH_TO_ARR(p,elemsize)) = temp;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
void * stbds_hmput_default(void *a, size_t elemsize)
|
void * stbds_hmput_default(void *a, size_t elemsize)
|
||||||
{
|
{
|
||||||
// three cases:
|
// three cases:
|
||||||
@ -1200,6 +1301,7 @@ static char *stbds_strdup(char *str);
|
|||||||
|
|
||||||
void *stbds_hmput_key(void *a, size_t elemsize, void *key, size_t keysize, int mode)
|
void *stbds_hmput_key(void *a, size_t elemsize, void *key, size_t keysize, int mode)
|
||||||
{
|
{
|
||||||
|
size_t keyoffset=0;
|
||||||
void *raw_a;
|
void *raw_a;
|
||||||
stbds_hash_index *table;
|
stbds_hash_index *table;
|
||||||
|
|
||||||
@ -1223,9 +1325,10 @@ void *stbds_hmput_key(void *a, size_t elemsize, void *key, size_t keysize, int m
|
|||||||
|
|
||||||
slot_count = (table == NULL) ? STBDS_BUCKET_LENGTH : table->slot_count*2;
|
slot_count = (table == NULL) ? STBDS_BUCKET_LENGTH : table->slot_count*2;
|
||||||
nt = stbds_make_hash_index(slot_count, table);
|
nt = stbds_make_hash_index(slot_count, table);
|
||||||
if (table) {
|
if (table)
|
||||||
STBDS_FREE(NULL, table);
|
STBDS_FREE(NULL, table);
|
||||||
}
|
else
|
||||||
|
nt->string.mode = mode >= STBDS_HM_STRING ? STBDS_SH_DEFAULT : 0;
|
||||||
stbds_header(a)->hash_table = table = nt;
|
stbds_header(a)->hash_table = table = nt;
|
||||||
STBDS_STATS(++stbds_hash_grow);
|
STBDS_STATS(++stbds_hash_grow);
|
||||||
}
|
}
|
||||||
@ -1251,7 +1354,7 @@ void *stbds_hmput_key(void *a, size_t elemsize, void *key, size_t keysize, int m
|
|||||||
// start searching from pos to end of bucket
|
// start searching from pos to end of bucket
|
||||||
for (i=pos & STBDS_BUCKET_MASK; i < STBDS_BUCKET_LENGTH; ++i) {
|
for (i=pos & STBDS_BUCKET_MASK; i < STBDS_BUCKET_LENGTH; ++i) {
|
||||||
if (bucket->hash[i] == hash) {
|
if (bucket->hash[i] == hash) {
|
||||||
if (stbds_is_key_equal(raw_a, elemsize, key, keysize, mode, bucket->index[i])) {
|
if (stbds_is_key_equal(raw_a, elemsize, key, keysize, keyoffset, mode, bucket->index[i])) {
|
||||||
stbds_temp(a) = bucket->index[i];
|
stbds_temp(a) = bucket->index[i];
|
||||||
return STBDS_ARR_TO_HASH(a,elemsize);
|
return STBDS_ARR_TO_HASH(a,elemsize);
|
||||||
}
|
}
|
||||||
@ -1268,7 +1371,7 @@ void *stbds_hmput_key(void *a, size_t elemsize, void *key, size_t keysize, int m
|
|||||||
limit = pos & STBDS_BUCKET_MASK;
|
limit = pos & STBDS_BUCKET_MASK;
|
||||||
for (i = 0; i < limit; ++i) {
|
for (i = 0; i < limit; ++i) {
|
||||||
if (bucket->hash[i] == hash) {
|
if (bucket->hash[i] == hash) {
|
||||||
if (stbds_is_key_equal(raw_a, elemsize, key, keysize, mode, bucket->index[i])) {
|
if (stbds_is_key_equal(raw_a, elemsize, key, keysize, keyoffset, mode, bucket->index[i])) {
|
||||||
stbds_temp(a) = bucket->index[i];
|
stbds_temp(a) = bucket->index[i];
|
||||||
return STBDS_ARR_TO_HASH(a,elemsize);
|
return STBDS_ARR_TO_HASH(a,elemsize);
|
||||||
}
|
}
|
||||||
@ -1310,7 +1413,8 @@ void *stbds_hmput_key(void *a, size_t elemsize, void *key, size_t keysize, int m
|
|||||||
switch (table->string.mode) {
|
switch (table->string.mode) {
|
||||||
case STBDS_SH_STRDUP: *(char **) ((char *) a + elemsize*i) = stbds_strdup((char*) key); break;
|
case STBDS_SH_STRDUP: *(char **) ((char *) a + elemsize*i) = stbds_strdup((char*) key); break;
|
||||||
case STBDS_SH_ARENA: *(char **) ((char *) a + elemsize*i) = stbds_stralloc(&table->string, (char*)key); break;
|
case STBDS_SH_ARENA: *(char **) ((char *) a + elemsize*i) = stbds_stralloc(&table->string, (char*)key); break;
|
||||||
default: *(char **) ((char *) a + elemsize*i) = (char *) key; break;
|
case STBDS_SH_DEFAULT: *(char **) ((char *) a + elemsize*i) = (char *) key; break;
|
||||||
|
default: memcpy((char *) a + elemsize*i, key, keysize); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return STBDS_ARR_TO_HASH(a,elemsize);
|
return STBDS_ARR_TO_HASH(a,elemsize);
|
||||||
@ -1324,7 +1428,7 @@ void * stbds_shmode_func(size_t elemsize, int mode)
|
|||||||
memset(a, 0, elemsize);
|
memset(a, 0, elemsize);
|
||||||
stbds_header(a)->length = 1;
|
stbds_header(a)->length = 1;
|
||||||
stbds_header(a)->hash_table = h = (stbds_hash_index *) stbds_make_hash_index(STBDS_BUCKET_LENGTH, NULL);
|
stbds_header(a)->hash_table = h = (stbds_hash_index *) stbds_make_hash_index(STBDS_BUCKET_LENGTH, NULL);
|
||||||
h->string.mode = mode;
|
h->string.mode = (unsigned char) mode;
|
||||||
return STBDS_ARR_TO_HASH(a,elemsize);
|
return STBDS_ARR_TO_HASH(a,elemsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1341,7 +1445,7 @@ void * stbds_hmdel_key(void *a, size_t elemsize, void *key, size_t keysize, size
|
|||||||
return a;
|
return a;
|
||||||
} else {
|
} else {
|
||||||
ptrdiff_t slot;
|
ptrdiff_t slot;
|
||||||
slot = stbds_hm_find_slot(a, elemsize, key, keysize, mode);
|
slot = stbds_hm_find_slot(a, elemsize, key, keysize, keyoffset, mode);
|
||||||
if (slot < 0)
|
if (slot < 0)
|
||||||
return a;
|
return a;
|
||||||
else {
|
else {
|
||||||
@ -1368,9 +1472,9 @@ void * stbds_hmdel_key(void *a, size_t elemsize, void *key, size_t keysize, size
|
|||||||
|
|
||||||
// now find the slot for the last element
|
// now find the slot for the last element
|
||||||
if (mode == STBDS_HM_STRING)
|
if (mode == STBDS_HM_STRING)
|
||||||
slot = stbds_hm_find_slot(a, elemsize, *(char**) ((char *) a+elemsize*old_index + keyoffset), keysize, mode);
|
slot = stbds_hm_find_slot(a, elemsize, *(char**) ((char *) a+elemsize*old_index + keyoffset), keysize, keyoffset, mode);
|
||||||
else
|
else
|
||||||
slot = stbds_hm_find_slot(a, elemsize, (char* ) a+elemsize*old_index + keyoffset, keysize, mode);
|
slot = stbds_hm_find_slot(a, elemsize, (char* ) a+elemsize*old_index + keyoffset, keysize, keyoffset, mode);
|
||||||
STBDS_ASSERT(slot >= 0);
|
STBDS_ASSERT(slot >= 0);
|
||||||
b = &table->storage[slot >> STBDS_BUCKET_SHIFT];
|
b = &table->storage[slot >> STBDS_BUCKET_SHIFT];
|
||||||
i = slot & STBDS_BUCKET_MASK;
|
i = slot & STBDS_BUCKET_MASK;
|
||||||
@ -1394,7 +1498,6 @@ void * stbds_hmdel_key(void *a, size_t elemsize, void *key, size_t keysize, size
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *stbds_strdup(char *str)
|
static char *stbds_strdup(char *str)
|
||||||
@ -1408,10 +1511,10 @@ static char *stbds_strdup(char *str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef STBDS_STRING_ARENA_BLOCKSIZE_MIN
|
#ifndef STBDS_STRING_ARENA_BLOCKSIZE_MIN
|
||||||
#define STBDS_STRING_ARENA_BLOCKSIZE_MIN 512
|
#define STBDS_STRING_ARENA_BLOCKSIZE_MIN 512u
|
||||||
#endif
|
#endif
|
||||||
#ifndef STBDS_STRING_ARENA_BLOCKSIZE_MAX
|
#ifndef STBDS_STRING_ARENA_BLOCKSIZE_MAX
|
||||||
#define STBDS_STRING_ARENA_BLOCKSIZE_MAX 1<<20
|
#define STBDS_STRING_ARENA_BLOCKSIZE_MAX (1u<<20)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char *stbds_stralloc(stbds_string_arena *a, char *str)
|
char *stbds_stralloc(stbds_string_arena *a, char *str)
|
||||||
@ -1492,6 +1595,7 @@ void stbds_strreset(stbds_string_arena *a)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct { int key,b,c,d; } stbds_struct;
|
typedef struct { int key,b,c,d; } stbds_struct;
|
||||||
|
typedef struct { int key[2],b,c,d; } stbds_struct2;
|
||||||
|
|
||||||
static char buffer[256];
|
static char buffer[256];
|
||||||
char *strkey(int n)
|
char *strkey(int n)
|
||||||
@ -1511,12 +1615,16 @@ void stbds_unit_tests(void)
|
|||||||
STBDS_ASSERT(0);
|
STBDS_ASSERT(0);
|
||||||
#else
|
#else
|
||||||
const int testsize = 100000;
|
const int testsize = 100000;
|
||||||
|
const int testsize2 = testsize/20;
|
||||||
int *arr=NULL;
|
int *arr=NULL;
|
||||||
struct { int key; int value; } *intmap = NULL;
|
struct { int key; int value; } *intmap = NULL;
|
||||||
struct { char *key; int value; } *strmap = NULL;
|
struct { char *key; int value; } *strmap = NULL;
|
||||||
struct { stbds_struct key; int value; } *map = NULL;
|
struct { stbds_struct key; int value; } *map = NULL;
|
||||||
stbds_struct *map2 = NULL;
|
stbds_struct *map2 = NULL;
|
||||||
|
stbds_struct2 *map3 = NULL;
|
||||||
stbds_string_arena sa = { 0 };
|
stbds_string_arena sa = { 0 };
|
||||||
|
int key3[2] = { 1,2 };
|
||||||
|
ptrdiff_t temp;
|
||||||
|
|
||||||
int i,j;
|
int i,j;
|
||||||
|
|
||||||
@ -1552,9 +1660,12 @@ void stbds_unit_tests(void)
|
|||||||
STBDS_ASSERT(hmget (intmap, i) == -2);
|
STBDS_ASSERT(hmget (intmap, i) == -2);
|
||||||
for (i=0; i < testsize; i+=2)
|
for (i=0; i < testsize; i+=2)
|
||||||
hmput(intmap, i, i*5);
|
hmput(intmap, i, i*5);
|
||||||
for (i=0; i < testsize; i+=1)
|
for (i=0; i < testsize; i+=1) {
|
||||||
if (i & 1) STBDS_ASSERT(hmget(intmap, i) == -2 );
|
if (i & 1) STBDS_ASSERT(hmget(intmap, i) == -2 );
|
||||||
else STBDS_ASSERT(hmget(intmap, i) == i*5);
|
else STBDS_ASSERT(hmget(intmap, i) == i*5);
|
||||||
|
if (i & 1) STBDS_ASSERT(hmget_ts(intmap, i, temp) == -2 );
|
||||||
|
else STBDS_ASSERT(hmget_ts(intmap, i, temp) == i*5);
|
||||||
|
}
|
||||||
for (i=0; i < testsize; i+=2)
|
for (i=0; i < testsize; i+=2)
|
||||||
hmput(intmap, i, i*3);
|
hmput(intmap, i, i*3);
|
||||||
for (i=0; i < testsize; i+=1)
|
for (i=0; i < testsize; i+=1)
|
||||||
@ -1639,7 +1750,9 @@ void stbds_unit_tests(void)
|
|||||||
stbds_struct t = { i,i*2,i*3+1,i*4 };
|
stbds_struct t = { i,i*2,i*3+1,i*4 };
|
||||||
if (i & 1) STBDS_ASSERT(hmget(map, s) == 0);
|
if (i & 1) STBDS_ASSERT(hmget(map, s) == 0);
|
||||||
else STBDS_ASSERT(hmget(map, s) == i*5);
|
else STBDS_ASSERT(hmget(map, s) == i*5);
|
||||||
STBDS_ASSERT(hmget(map, t) == 0);
|
if (i & 1) STBDS_ASSERT(hmget_ts(map, s, temp) == 0);
|
||||||
|
else STBDS_ASSERT(hmget_ts(map, s, temp) == i*5);
|
||||||
|
//STBDS_ASSERT(hmget(map, t.key) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0; i < testsize; i += 2) {
|
for (i=0; i < testsize; i += 2) {
|
||||||
@ -1653,9 +1766,21 @@ void stbds_unit_tests(void)
|
|||||||
stbds_struct t = { i,i*2,i*3+1,i*4 };
|
stbds_struct t = { i,i*2,i*3+1,i*4 };
|
||||||
if (i & 1) STBDS_ASSERT(hmgets(map2, s.key).d == 0);
|
if (i & 1) STBDS_ASSERT(hmgets(map2, s.key).d == 0);
|
||||||
else STBDS_ASSERT(hmgets(map2, s.key).d == i*4);
|
else STBDS_ASSERT(hmgets(map2, s.key).d == i*4);
|
||||||
STBDS_ASSERT(hmget(map, t) == 0);
|
//STBDS_ASSERT(hmgetp(map2, t.key) == 0);
|
||||||
}
|
}
|
||||||
hmfree(map2);
|
hmfree(map2);
|
||||||
|
|
||||||
|
for (i=0; i < testsize; i += 2) {
|
||||||
|
stbds_struct2 s = { { i,i*2 }, i*3,i*4, i*5 };
|
||||||
|
hmputs(map3, s);
|
||||||
|
}
|
||||||
|
for (i=0; i < testsize; i += 1) {
|
||||||
|
stbds_struct2 s = { { i,i*2}, i*3, i*4, i*5 };
|
||||||
|
stbds_struct2 t = { { i,i*2}, i*3+1, i*4, i*5 };
|
||||||
|
if (i & 1) STBDS_ASSERT(hmgets(map3, s.key).d == 0);
|
||||||
|
else STBDS_ASSERT(hmgets(map3, s.key).d == i*5);
|
||||||
|
//STBDS_ASSERT(hmgetp(map3, t.key) == 0);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user