From f9133c36771b2ea7358951a25ecd27d70cbb90ea Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 25 Feb 2019 13:48:41 -0800 Subject: [PATCH] stb_ds v0.3: fixes for compiling client code in C++ add missing _wrapper suffixes disable clang rvalue support in C++ disable unit tests in VC6 C++ other tweaks --- README.md | 4 +-- stb_ds.h | 83 +++++++++++++++++++++++++++++++------------------------ 2 files changed, 49 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index a24af47..13db773 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ library | lastest version | category | LoC | description **[stb_image_write.h](stb_image_write.h)** | 1.11 | graphics | 1621 | image writing to disk: PNG, TGA, BMP **[stb_image_resize.h](stb_image_resize.h)** | 0.95 | graphics | 2627 | resize images larger/smaller with good quality **[stb_rect_pack.h](stb_rect_pack.h)** | 1.00 | graphics | 628 | simple 2D rectangle packer with decent quality -**[stb_ds.h](stb_ds.h)** | 0.2 | utility | 1627 | typesafe dynamic array and hash tables for C, will compile in C++ +**[stb_ds.h](stb_ds.h)** | 0.3 | utility | 1638 | typesafe dynamic array and hash tables for C, will compile in C++ **[stb_sprintf.h](stb_sprintf.h)** | 1.06 | utility | 1860 | fast sprintf, snprintf for C/C++ **[stretchy_buffer.h](stretchy_buffer.h)** | 1.03 | utility | 262 | typesafe dynamic array for C (i.e. approximation to vector<>), doesn't compile as C++ **[stb_textedit.h](stb_textedit.h)** | 1.13 | user interface | 1404 | guts of a text editor for games etc implementing them from scratch @@ -34,7 +34,7 @@ library | lastest version | category | LoC | description **[stb_leakcheck.h](stb_leakcheck.h)** | 0.5 | misc | 190 | quick-and-dirty malloc/free leak-checking Total libraries: 21 -Total lines of C code: 55609 +Total lines of C code: 55620 FAQ diff --git a/stb_ds.h b/stb_ds.h index ca1a453..96c64d5 100644 --- a/stb_ds.h +++ b/stb_ds.h @@ -1,4 +1,4 @@ -/* stb_ds.h - v0.2 - public domain data structures - Sean Barrett 2019 +/* stb_ds.h - v0.3 - public domain data structures - Sean Barrett 2019 This is a single-header-file library that provides easy-to-use dynamic arrays and hash tables for C (also works in C++). @@ -402,7 +402,7 @@ extern void * stbds_shmode_func(size_t elemsize, int mode); #if defined(__GNUC__) || defined(__clang__) #define STBDS_HAS_TYPEOF #ifdef __cplusplus -#define STBDS_HAS_LITERAL_ARRAY +//#define STBDS_HAS_LITERAL_ARRAY // this is currently broken for clang #endif #endif @@ -414,7 +414,11 @@ extern void * stbds_shmode_func(size_t elemsize, int mode); // this macro takes the address of the argument, but on gcc/clang can accept rvalues #if defined(STBDS_HAS_LITERAL_ARRAY) && defined(STBDS_HAS_TYPEOF) -#define STBDS_ADDRESSOF(typevar, value) ((typeof(typevar)[1]){value}) // literal array decays to pointer to value + #if __clang__ + #define STBDS_ADDRESSOF(typevar, value) ((__typeof__(typevar)[1]){value}) // literal array decays to pointer to value + #else + #define STBDS_ADDRESSOF(typevar, value) ((typeof(typevar)[]){value}) // literal array decays to pointer to value + #endif #else #define STBDS_ADDRESSOF(typevar, value) &(value) #endif @@ -443,10 +447,10 @@ extern void * stbds_shmode_func(size_t elemsize, int mode); #define stbds_arrmaybegrow(a,n) ((!(a) || stbds_header(a)->length + (n) > stbds_header(a)->capacity) \ ? (stbds_arrgrow(a,n,0),0) : 0) -#define stbds_arrgrow(a,b,c) ((a) = stbds_arrgrowf((a), sizeof *(a), (b), (c))) +#define stbds_arrgrow(a,b,c) ((a) = stbds_arrgrowf_wrapper((a), sizeof *(a), (b), (c))) #define stbds_hmput(t, k, v) \ - ((t) = stbds_hmput_key_wrapper((t), sizeof *(t), STBDS_ADDRESSOF((t)->key, (k)), sizeof (t)->key, 0), \ + ((t) = stbds_hmput_key_wrapper((t), sizeof *(t), (void*) STBDS_ADDRESSOF((t)->key, (k)), sizeof (t)->key, 0), \ (t)[stbds_temp((t)-1)].key = (k), \ (t)[stbds_temp((t)-1)].value = (v)) @@ -455,14 +459,14 @@ extern void * stbds_shmode_func(size_t elemsize, int mode); (t)[stbds_temp((t)-1)] = (s)) #define stbds_hmgeti(t,k) \ - ((t) = stbds_hmget_key_wrapper((t), sizeof *(t), 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)) #define stbds_hmgetp(t, k) \ ((void) stbds_hmgeti(t,k), &(t)[stbds_temp((t)-1)]) #define stbds_hmdel(t,k) \ - (((t) = stbds_hmdel_key_wrapper((t),sizeof *(t), 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) #define stbds_hmdefault(t, v) \ ((t) = stbds_hmput_default_wrapper((t), sizeof *(t)), (t)[-1].value = (v)) @@ -479,22 +483,22 @@ extern void * stbds_shmode_func(size_t elemsize, int mode); #define stbds_hmlenu(t) (stbds_arrlenu((t)-1)-1) #define stbds_shput(t, k, v) \ - ((t) = stbds_hmput_key_wrapper((t), sizeof *(t), (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)) #define stbds_shputs(t, s) \ - ((t) = stbds_hmput_key_wrapper((t), sizeof *(t), (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)) #define stbds_shgeti(t,k) \ - ((t) = stbds_hmget_key_wrapper((t), sizeof *(t), (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)) #define stbds_shgetp(t, k) \ ((void) stbds_shgeti(t,k), &(t)[stbds_temp(t-1)]) #define stbds_shdel(t,k) \ - (((t) = stbds_hmdel_key((t),sizeof *(t), (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_sh_new_arena(t) \ ((t) = stbds_shmode_func_wrapper(t, sizeof *(t), STBDS_SH_ARENA)) @@ -565,7 +569,7 @@ template static T * stbds_hmdel_key_wrapper(T *a, size_t elemsize, void return (T*)stbds_hmdel_key((void*)a, elemsize, key, keysize, keyoffset, mode); } template static T * stbds_shmode_func_wrapper(T *, size_t elemsize, int mode) { - return stbds_shmode_func(elemsize, mode); + return (T*)stbds_shmode_func(elemsize, mode); } #else #define stbds_arrgrowf_wrapper stbds_arrgrowf @@ -1444,6 +1448,10 @@ char *strkey(int n) void stbds_unit_tests(void) { +#if defined(_MSC_VER) && _MSC_VER <= 1200 && defined(__cplusplus) + // VC6 C++ doesn't like the template<> trick on unnamed structures, so do nothing! + STBDS_ASSERT(0); +#else const int testsize = 100000; int *arr=NULL; struct { int key; int value; } *intmap = NULL; @@ -1472,46 +1480,48 @@ void stbds_unit_tests(void) for (i=0; i < 5; ++i) { arrpush(arr,1); arrpush(arr,2); arrpush(arr,3); arrpush(arr,4); stbds_arrins(arr,i,5); - assert(arr[i] == 5); + STBDS_ASSERT(arr[i] == 5); if (i < 4) - assert(arr[4] == 4); + STBDS_ASSERT(arr[4] == 4); arrfree(arr); } hmdefault(intmap, -1); - i=1; assert(hmget(intmap, i) == -1); + i=1; STBDS_ASSERT(hmget(intmap, i) == -1); for (i=0; i < testsize; i+=2) hmput(intmap, i, i*5); for (i=0; i < testsize; i+=1) - if (i & 1) assert(hmget(intmap, i) == -1 ); - else assert(hmget(intmap, i) == i*5); + if (i & 1) STBDS_ASSERT(hmget(intmap, i) == -1 ); + else STBDS_ASSERT(hmget(intmap, i) == i*5); for (i=0; i < testsize; i+=2) hmput(intmap, i, i*3); for (i=0; i < testsize; i+=1) - if (i & 1) assert(hmget(intmap, i) == -1 ); - else assert(hmget(intmap, i) == i*3); + if (i & 1) STBDS_ASSERT(hmget(intmap, i) == -1 ); + else STBDS_ASSERT(hmget(intmap, i) == i*3); for (i=2; i < testsize; i+=4) hmdel(intmap, i); // delete half the entries for (i=0; i < testsize; i+=1) - if (i & 3) assert(hmget(intmap, i) == -1 ); - else assert(hmget(intmap, i) == i*3); + if (i & 3) STBDS_ASSERT(hmget(intmap, i) == -1 ); + else STBDS_ASSERT(hmget(intmap, i) == i*3); for (i=0; i < testsize; i+=1) hmdel(intmap, i); // delete the rest of the entries for (i=0; i < testsize; i+=1) - assert(hmget(intmap, i) == -1 ); + STBDS_ASSERT(hmget(intmap, i) == -1 ); hmfree(intmap); for (i=0; i < testsize; i+=2) hmput(intmap, i, i*3); hmfree(intmap); - #ifdef __clang__ + #if defined(__clang__) || defined(__GNUC__) + #ifndef __cplusplus intmap = NULL; hmput(intmap, 15, 7); hmput(intmap, 11, 3); hmput(intmap, 9, 5); - assert(hmget(intmap, 9) == 5); - assert(hmget(intmap, 11) == 3); - assert(hmget(intmap, 15) == 7); + STBDS_ASSERT(hmget(intmap, 9) == 5); + STBDS_ASSERT(hmget(intmap, 11) == 3); + STBDS_ASSERT(hmget(intmap, 15) == 7); + #endif #endif for (i=0; i < testsize; ++i) @@ -1527,17 +1537,17 @@ void stbds_unit_tests(void) for (i=0; i < testsize; i+=2) shput(strmap, strkey(i), i*3); for (i=0; i < testsize; i+=1) - if (i & 1) assert(shget(strmap, strkey(i)) == -1 ); - else assert(shget(strmap, strkey(i)) == i*3); + if (i & 1) STBDS_ASSERT(shget(strmap, strkey(i)) == -1 ); + else STBDS_ASSERT(shget(strmap, strkey(i)) == i*3); for (i=2; i < testsize; i+=4) shdel(strmap, strkey(i)); // delete half the entries for (i=0; i < testsize; i+=1) - if (i & 3) assert(shget(strmap, strkey(i)) == -1 ); - else assert(shget(strmap, strkey(i)) == i*3); + if (i & 3) STBDS_ASSERT(shget(strmap, strkey(i)) == -1 ); + else STBDS_ASSERT(shget(strmap, strkey(i)) == i*3); for (i=0; i < testsize; i+=1) shdel(strmap, strkey(i)); // delete the rest of the entries for (i=0; i < testsize; i+=1) - assert(shget(strmap, strkey(i)) == -1 ); + STBDS_ASSERT(shget(strmap, strkey(i)) == -1 ); shfree(strmap); } @@ -1562,9 +1572,9 @@ void stbds_unit_tests(void) for (i=0; i < testsize; i += 1) { stbds_struct s = { i,i*2,i*3 ,i*4 }; stbds_struct t = { i,i*2,i*3+1,i*4 }; - if (i & 1) assert(hmget(map, s) == 0); - else assert(hmget(map, s) == i*5); - assert(hmget(map, t) == 0); + if (i & 1) STBDS_ASSERT(hmget(map, s) == 0); + else STBDS_ASSERT(hmget(map, s) == i*5); + STBDS_ASSERT(hmget(map, t) == 0); } for (i=0; i < testsize; i += 2) { @@ -1576,10 +1586,11 @@ void stbds_unit_tests(void) for (i=0; i < testsize; i += 1) { stbds_struct s = { i,i*2,i*3,i*4 }; stbds_struct t = { i,i*2,i*3,i*4 }; - if (i & 1) assert(hmgets(map2, s.key).d == 0); - else assert(hmgets(map2, s.key).d == i*4); + if (i & 1) STBDS_ASSERT(hmgets(map2, s.key).d == 0); + else STBDS_ASSERT(hmgets(map2, s.key).d == i*4); } hmfree(map2); +#endif } #endif