commit fedd0c7ed467aa9861379d400a09d0a4354fc0b3
parent 3e5433eacfa56238f5f2899620f7a5a52f9b953d
Author: Samdal <samdal@protonmail.com>
Date: Sun, 29 Jan 2023 12:21:55 +0100
clean up and seperate
Diffstat:
M | README.md | | | 85 | +------------------------------------------------------------------------------ |
M | proc/linux/Makefile | | | 2 | +- |
M | source/main.c | | | 326 | ++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------- |
3 files changed, 218 insertions(+), 195 deletions(-)
diff --git a/README.md b/README.md
@@ -1,88 +1,5 @@
# gs_bucket_array
-For up-to-date stuff look at source file
-
I have seperated the gs implementation into gs.c, but the build files are not all updated compile it.
-You have to do that if you want to compie the example.
-
-
-
-
-
-NOTE:
-> Unlike the other gunslinger containers, the gs_bucket_array needs initialization.
-> It is NOT allocated on use.
-
-Bucket arrays are internally a list of pointers to fixed-size arrays;
-This means that there are no realloc's, and all your pointers will remain valid.
-
-Due to the nature of this container it's very handy for managing both stuff that are
-"constant" and dynamic in a singular place.
-
-Because of this the container also has a bit-field that specifies which elements are in use.
-This creates an interface almost identitcal to gs_slot_array.
-The major drawback of this is a somewhat slow iterator and insertion.
-
-### The guts look somewhat like:
-
- gs_dyn_array(Type[bucket_size]) your_data;
- gs_dyn_array(int64_t) bit_field;
-
-### Standard initializatoin would look like:
-
- gs_bucket_array(float) arr = gs_bucket_array_new(float, 100); // Bucket array with internal 'float' data, where each bucket is 100 floats
- uint32_t hndl = gs_bucket_array_insert(arr, 3.145f); // Inserts your data into the bucket array, returns handle to you
- float* val_p = gs_bucket_array_getp(arr, hndl); // Returns copy of data to you using handle as lookup
- float val = gs_bucket_array_get(arr, hndl);
-
-
-### The bucket array provides iterators:
-
- for (
- gs_bucket_array_iter it = gs_bucket_array_iter_new(ba);
- gs_bucket_array_iter_valid(ba, it);
- gs_bucket_array_iter_advance(ba, it)
- ) {
- float v = gs_bucket_array_get(ba, it); // Get value using iterator
- float* vp = gs_bucket_array_getp(ba, it); // Get value pointer using iterator
- }
-
-This iterator gathers a index into the bucket array, which you later can use to get pointers/values
-through the indirection.
-However you might not always need this.
-If you don't care about elements being "valid" you can use the fast iterator:
-
- for (
- gs_bucket_array_iter_fast it = gs_bucket_array_iter_fast_new(ba);
- gs_bucket_array_iter_fast_valid(ba, it);
- gs_bucket_array_iter_fast_advance(ba, it)
- ) {
- float v = gs_bucket_array_iter_fast_get(ba, it); // Get value using iterator
- float* vp = gs_bucket_array_iter_fast_getp(ba, it); // Get value pointer using iterator
- uint32_t hndl = gs_bucket_array_iter_fast_get_hndl(ba, it); // Get a normal handle from iterator
- }
-
-Internally the fast iterator is just `struct {uint32_t major; uint32_t minor;}`
-
-
-TIP:
-> You may store your own "bool enabled;" in what you store in the bucket array.
-> You can then use the fast iterator and check for this yourself.
-> However, note that this needs gs_bucket_array_new_ex where null_new_buckets is set to true,
-> this is because un-initialized data will otherwise cause problems.
-
-
-### Normal bucket array usage:
-
- gs_bucket_array(float) ba = gs_bucket_array_new(float, 100); // Bucket array with internal 'float' data, where each bucket is 100 floats
- uint32_t hndl = gs_bucket_array_insert(ba, 3.145f); // Inserts your data into the bucket array, returns handle to you
- float* val_p = gs_bucket_array_getp(ba, hndl); // Returns your data to you using handle as lookup
- float val = gs_bucket_array_get(ba, hndl); // Dereferences your data as well
- uint32_t bs = gs_bucket_array_bucket_size(ba) // Returns initialized bucket size
- uint32_t bc = gs_bucket_array_bucket_count(ba) // Returns the amount of buckets allocated
- uint32_t b_cap = gs_bucket_array_capacity(ba) // Returns bucket_size * bucket_count
- gs_bucket_array_clear(ba) // Sets the entire bit-field to 0
- gs_bucket_array_free(ba) // Free's the entire array, make sure your own elements are free'd first
+So you might have to do that if you want to compile the example.
- // if you use new_ex, you can set a bool to memset every new bucket to zero
- gs_bucket_array(int) ba_null_on_new = gs_bucket_array_new_ex(int, 64, true);
diff --git a/proc/linux/Makefile b/proc/linux/Makefile
@@ -3,7 +3,7 @@
# options
CC = clang
LINKER = $(CC)
-CFLAGS = -O3 -pthread -g -std=gnu99 -Wall -Wno-missing-braces -Wno-unused-variable -Wno-switch -Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable -Wno-comment -Wno-typedef-redefinition #-Wfatal-errors
+CFLAGS = -O0 -pthread -g -std=gnu99 -Wall -Wno-missing-braces -Wno-unused-variable -Wno-switch -Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable -Wno-comment -Wno-typedef-redefinition #-Wfatal-errors
LFLAGS = -ldl -lX11 -lXi -lm -lpthread -lavformat -lavcodec -lswscale -lavutil
TARGET = App
diff --git a/source/main.c b/source/main.c
@@ -1,56 +1,97 @@
#include <gs/gs.h>
+// comment out this line to disable bit field
+//#define GS_BUCKET_ARRAY_BIT_FIELD
+
+
#define GS_BUCKET_ARRAY_INVALID_HANDLE UINT32_MAX
#define __gs_bucket_array_raw(__T) \
struct \
{ \
uint32_t bucket_size; \
- uint32_t null_buckets; \
+ uint32_t top; \
gs_dyn_array(int64_t) bit_field; \
gs_dyn_array(__T*) data; \
__T tmp; \
}
+
#define gs_bucket_array(__T)\
__gs_bucket_array_raw(__T)*
-#define gs_bucket_array_new_ex(__T, __AMOUNT, __NULL_NEW_BUCKETS)\
- __gs_bucket_array_new(__AMOUNT, sizeof(__gs_bucket_array_raw(__T)), __NULL_NEW_BUCKETS)
-
#define gs_bucket_array_new(__T, __AMOUNT)\
- gs_bucket_array_new_ex(__T, __AMOUNT, 0)
+ __gs_bucket_array_new(__AMOUNT, sizeof(__gs_bucket_array_raw(__T)))
gs_force_inline void*
-__gs_bucket_array_new(uint32_t amount, size_t struct_size, uint32_t null_buckets)
+__gs_bucket_array_new(uint32_t amount, size_t struct_size)
{
void* ret = malloc(struct_size);
memset(ret, 0, struct_size);
uint32_t* i = ret;
i[0] = amount;
- i[1] = null_buckets;
return ret;
}
#define gs_bucket_array_bucket_size(__BA) ((__BA)->bucket_size)
#define gs_bucket_array_bucket_count(__BA) (gs_dyn_array_size((__BA)->data))
#define gs_bucket_array_capacity(__BA) ((__BA)->bucket_size * gs_dyn_array_size((__BA)->data))
-
-#define gs_bucket_array_exists(__BA, __HNDL)\
- (__HNDL / (__BA)->bucket_size > gs_dyn_array_size((__BA)->data) ? false : \
- __gs_bucket_array_check((__BA)->bit_field, __HNDL) ? \
- true : false)
+#define gs_bucket_array_size(__BA) ((__BA)->top)
#define gs_bucket_array_get(__BA, __HNDL)\
(__BA)->data[(__HNDL) / (__BA)->bucket_size][(__HNDL) - (__HNDL) / (__BA)->bucket_size * (__BA)->bucket_size]
#define gs_bucket_array_getp(__BA, __HNDL) &gs_bucket_array_get(__BA, __HNDL)
-#define gs_bucket_array_insert(__BA, __VAL)\
+#define gs_bucket_array_push(__BA, __VAL)\
+ ((__BA)->tmp = __VAL, \
+ __gs_bucket_array_push_func((void***)&((__BA)->data), (__BA)->bucket_size, \
+ &(__BA)->tmp, sizeof((__BA)->tmp), &(__BA)->top))
+
+#define gs_bucket_array_reserve(__BA, __NUM_BUCKETS)\
+ (__gs_bucket_array_reserve_func((void***)&((__BA)->data), (__BA)->bucket_size, sizeof((__BA)->tmp), __NUM_BUCKETS))
+
+gs_force_inline void
+__gs_bucket_array_reserve_func(void*** dynarr, uint32_t bucket_size, uint32_t element_size, uint32_t num_buckets)
+{
+ while (num_buckets--) {
+ void* ptr = malloc(element_size * bucket_size);
+ gs_dyn_array_push_data((void**)dynarr, &ptr, sizeof(ptr));
+ }
+}
+
+gs_force_inline void
+__gs_bucket_array_push_func(void*** dynarr, uint32_t bucket_size,
+ void* element, size_t element_size, uint32_t* top)
+{
+ uint32_t sz = gs_dyn_array_size(*dynarr);
+ void* ptr;
+ if (!sz || *top >= bucket_size * sz) {
+ ptr = malloc(element_size * bucket_size);
+ gs_dyn_array_push_data((void**)dynarr, &ptr, sizeof(ptr));
+ } else {
+ const uint32_t major = *top / bucket_size;
+ ptr = (char*)dynarr[0][major] + ((*top - major * bucket_size) * element_size);
+ }
+ *top += 1;
+ memcpy(ptr, element, element_size);
+}
+
+
+
+#ifdef GS_BUCKET_ARRAY_BIT_FIELD
+// optional bit field functions
+
+#define gs_bucket_array_bf_exists(__BA, __HNDL)\
+ (__HNDL / (__BA)->bucket_size > gs_dyn_array_size((__BA)->data) ? false : \
+ __gs_bucket_array_check((__BA)->bit_field, __HNDL) ? \
+ true : false)
+
+#define gs_bucket_array_bf_insert(__BA, __VAL)\
((__BA)->tmp = __VAL, \
__gs_bucket_array_insert_into_any_bucket((void***)&((__BA)->data), &(__BA)->bit_field, (__BA)->bucket_size, \
- &(__BA)->tmp, sizeof((__BA)->tmp), (__BA)->null_buckets))
+ &(__BA)->tmp, sizeof((__BA)->tmp), &(__BA)->top))
-#define gs_bucket_array_erase(__BA, __HNDL)\
+#define gs_bucket_array_bf_erase(__BA, __HNDL)\
__gs_bucket_array_clear_bucket((__BA)->bit_field, __HNDL)
gs_force_inline bool32_t
@@ -72,35 +113,38 @@ __gs_bucket_array_clear_bucket(int64_t* bit_field, uint32_t index)
}
gs_force_inline uint32_t
-__gs_bucket_array_insert_into_any_bucket(void*** dynarr, int64_t** bit_field_dynarr,
- uint32_t bucket_size, void* element, size_t element_size, uint32_t null_buckets)
+__gs_bucket_array_insert_into_any_bucket(void*** dynarr, int64_t** bit_field_dynarr, uint32_t bucket_size,
+ void* element, size_t element_size, uint32_t* top)
{
uint32_t index;
uint32_t bit_sz = gs_dyn_array_size(*bit_field_dynarr);
uint32_t sz = gs_dyn_array_size(*dynarr);
- for (uint32_t i = 0; i < bit_sz; i++) {
- int pos = ffsll(~bit_field_dynarr[0][i]);
- if (pos) {
- index = pos - 1 + i * 64;
- if (index >= sz * bucket_size) break;
-
- void* p = (char*)dynarr[0][index / bucket_size] + (index - index / bucket_size * bucket_size) * element_size;
- memcpy(p, element, element_size);
- bit_field_dynarr[0][i] |= 1L << (pos - 1);
- return index;
+ if (bit_sz) {
+ for (uint32_t i = bit_sz - 1; i != UINT32_MAX; i--) {
+ int pos = ffsll(~bit_field_dynarr[0][i]);
+ if (pos) {
+ index = pos - 1 + i * 64;
+ if (index >= sz * bucket_size) continue;
+
+ const uint32_t bucket_index = index - index / bucket_size * bucket_size;
+ void* p = (char*)dynarr[0][index / bucket_size] + bucket_index * element_size;
+ memcpy(p, element, element_size);
+ bit_field_dynarr[0][i] |= 1L << (pos - 1);
+ return index;
+ }
}
}
void* tmp_ptr = malloc(element_size * bucket_size);
memcpy(tmp_ptr, element, element_size);
- if (null_buckets) memset((char*)tmp_ptr + element_size, 0, (element_size - 1) * bucket_size);
gs_dyn_array_push_data((void**)dynarr, &tmp_ptr, sizeof(tmp_ptr));
index = bucket_size * sz;
uint32_t last_field_end = index + ((index % 64) ? (64 - index % 64) : 0);
uint32_t index_end = index + bucket_size;
+ *top = index_end;
uint32_t new_index_field_end = index_end + ((index_end % 64) ? (64 - index_end % 64) : 0);
uint32_t new_bit_size = (new_index_field_end - last_field_end) / 64;
@@ -113,14 +157,40 @@ __gs_bucket_array_insert_into_any_bucket(void*** dynarr, int64_t** bit_field_dyn
return sz * bucket_size;
}
-// normal iter
-#define gs_bucket_array_iter uint32_t
-#define gs_bucket_array_iter_new(__BA) __gs_bucket_array_iter_new_func((__BA)->bit_field, (__BA)->bucket_size * gs_bucket_array_bucket_count(__BA))
-#define gs_bucket_array_iter_valid(__BA, __IT) (__IT != GS_BUCKET_ARRAY_INVALID_HANDLE)
-#define gs_bucket_array_iter_advance(__BA, __IT) __gs_bucket_array_advance_func((__BA)->bit_field, &__IT, (__BA)->bucket_size * gs_bucket_array_bucket_count(__BA))
+#define gs_bucket_array_bf_reserve(__BA, __NUM_BUCKETS)\
+ (__gs_bucket_array_bf_reserve_func((void***)&((__BA)->data), (__BA)->bucket_size, sizeof((__BA)->tmp),\
+ __NUM_BUCKETS, &(__BA)->bit_field, &(__BA)->top))
+
+gs_force_inline void
+__gs_bucket_array_bf_reserve_func(void*** dynarr, uint32_t bucket_size, uint32_t element_size,
+ uint32_t num_buckets, int64_t** bit_field_dynarr, uint32_t* top)
+{
+ uint32_t sz = gs_dyn_array_size(*dynarr);
+
+ __gs_bucket_array_reserve_func(dynarr, bucket_size, element_size, num_buckets);
+
+ uint32_t index = bucket_size * sz;
+ uint32_t last_field_end = index + ((index % 64) ? (64 - index % 64) : 0);
+
+ uint32_t index_end = index + bucket_size * num_buckets;
+ *top = index_end;
+ uint32_t new_index_field_end = index_end + ((index_end % 64) ? (64 - index_end % 64) : 0);
+
+ uint32_t new_bit_size = (new_index_field_end - last_field_end) / 64;
+ int64_t tmp = 0;
+ for (uint32_t i = 0; i < new_bit_size; i++)
+ gs_dyn_array_push(*bit_field_dynarr, tmp);
+}
+
+// bit field iter
+// the iter is a hndl into the bit field / array
+#define gs_bucket_array_iter_bf uint32_t
+#define gs_bucket_array_iter_bf_new(__BA) __gs_bucket_array_iter_bf_new_func((__BA)->bit_field, (__BA)->bucket_size * gs_bucket_array_bucket_count(__BA))
+#define gs_bucket_array_iter_bf_valid(__BA, __IT) (__IT != GS_BUCKET_ARRAY_INVALID_HANDLE)
+#define gs_bucket_array_iter_bf_advance(__BA, __IT) __gs_bucket_array_bf_advance_func((__BA)->bit_field, &__IT, (__BA)->bucket_size * gs_bucket_array_bucket_count(__BA))
gs_force_inline uint32_t
-__gs_bucket_array_iter_new_func(int64_t* bit_field, uint32_t max_index)
+__gs_bucket_array_iter_bf_new_func(int64_t* bit_field, uint32_t max_index)
{
uint32_t res = 1;
uint32_t idx = 0;
@@ -136,7 +206,7 @@ __gs_bucket_array_iter_new_func(int64_t* bit_field, uint32_t max_index)
}
gs_force_inline void
-__gs_bucket_array_advance_func(int64_t* bit_field, uint32_t* index, uint32_t max_index)
+__gs_bucket_array_bf_advance_func(int64_t* bit_field, uint32_t* index, uint32_t max_index)
{
uint32_t res = 0;
do {
@@ -149,18 +219,21 @@ __gs_bucket_array_advance_func(int64_t* bit_field, uint32_t* index, uint32_t max
} while (!res);
}
-// fast iter
-typedef struct gs_bucket_array_iter_fast_s {
+#endif // GS_BUCKET_ARRAY_BIT_FIELD
+
+
+// normal iter
+typedef struct gs_bucket_array_iter_s {
uint32_t major;
uint32_t minor;
-} gs_bucket_array_iter_fast;
+} gs_bucket_array_iter;
-#define gs_bucket_array_iter_fast_new(__BA) gs_default_val()
-#define gs_bucket_array_iter_fast_valid(__BA, __IT) (__IT.major < gs_bucket_array_bucket_count(__BA))
-#define gs_bucket_array_iter_fast_advance(__BA, __IT) __gs_bucket_array_fast_advance_func(&__IT, (__BA)->bucket_size)
+#define gs_bucket_array_iter_new(__BA) gs_default_val()
+#define gs_bucket_array_iter_valid(__BA, __IT) (__IT.major * (__BA)->bucket_size + __IT.minor < (__BA)->top)
+#define gs_bucket_array_iter_advance(__BA, __IT) __gs_bucket_array_advance_func(&__IT, (__BA)->bucket_size)
gs_force_inline void
-__gs_bucket_array_fast_advance_func(gs_bucket_array_iter_fast* it, uint32_t bucket_size)
+__gs_bucket_array_advance_func(gs_bucket_array_iter* it, uint32_t bucket_size)
{
it->minor += 1;
if (it->minor >= bucket_size) {
@@ -168,13 +241,13 @@ __gs_bucket_array_fast_advance_func(gs_bucket_array_iter_fast* it, uint32_t buck
it->major += 1;
}
}
-#define gs_bucket_array_iter_fast_get(__BA, __IT)\
+#define gs_bucket_array_iter_get(__BA, __IT)\
(__BA)->data[__IT.major][__IT.minor]
-#define gs_bucket_array_iter_fast_getp(__BA, __IT)\
- &gs_bucket_array_iter_fast_get(__BA, __IT)
+#define gs_bucket_array_iter_getp(__BA, __IT)\
+ &gs_bucket_array_iter_get(__BA, __IT)
-#define gs_bucket_array_iter_fast_get_hndl(__BA, __IT)\
+#define gs_bucket_array_iter_get_hndl(__BA, __IT)\
(__IT.major * (__BA)->bucket_size + __IT.minor)
@@ -182,10 +255,12 @@ __gs_bucket_array_fast_advance_func(gs_bucket_array_iter_fast* it, uint32_t buck
#define gs_bucket_array_clear(__BA)\
memset((__BA)->bit_field, 0, gs_dyn_array_size((__BA)->bit_field) * sizeof(int64_t));
+
#define gs_bucket_array_free(__BA)\
do { \
if (__BA) { \
- gs_dyn_array_free((__BA)->bit_field); \
+ if ((__BA)->bit_field) \
+ gs_dyn_array_free((__BA)->bit_field); \
for (uint32_t __BA_IT = 0; __BA_IT < gs_dyn_array_size((__BA)->data); __BA_IT++) \
gs_free((__BA)->data[__BA_IT]); \
gs_dyn_array_free((__BA)->data); \
@@ -194,6 +269,7 @@ __gs_bucket_array_fast_advance_func(gs_bucket_array_iter_fast* it, uint32_t buck
} \
} while (0)
+
/*
gs_bucket_array:
@@ -207,99 +283,124 @@ __gs_bucket_array_fast_advance_func(gs_bucket_array_iter_fast* it, uint32_t buck
Due to the nature of this container it's very handy for managing both stuff that are
"constant" and dynamic in a singular place.
-
- Because of this the container also has a bit-field that specifies which elements are in use.
- This creates an interface almost identitcal to gs_slot_array.
- The major drawback of this is a somewhat slow iterator and insertion.
+ The major drawback of this is slower insertion and iteration.
The guts look somewhat like:
gs_dyn_array(Type[bucket_size]) your_data;
- gs_dyn_array(int64_t) bit_field;
Standard initializatoin would look like:
gs_bucket_array(float) arr = gs_bucket_array_new(float, 100); // Bucket array with internal 'float' data, where each bucket is 100 floats
- uint32_t hndl = gs_bucket_array_insert(arr, 3.145f); // Inserts your data into the bucket array, returns handle to you
- float* val_p = gs_bucket_array_getp(arr, hndl); // Returns copy of data to you using handle as lookup
- float val = gs_bucket_array_get(arr, hndl);
-
+ gs_bucket_array_push(arr, 3.145f); // Pushes 3.145 into the array
+ float* val_p = gs_bucket_array_getp(arr, index);
+ float val = gs_bucket_array_get(arr, index);
- The Bucket array provides iterators:
+ The bucket array provides iterators:
for (
gs_bucket_array_iter it = gs_bucket_array_iter_new(ba);
gs_bucket_array_iter_valid(ba, it);
gs_bucket_array_iter_advance(ba, it)
) {
- float v = gs_bucket_array_get(ba, it); // Get value using iterator
- float* vp = gs_bucket_array_getp(ba, it); // Get value pointer using iterator
+ float v = gs_bucket_array_iter_get(ba, it); // Get value using iterator
+ float* vp = gs_bucket_array_iter_getp(ba, it); // Get value pointer using iterator
}
- This iterator gathers a index into the bucket array, which you later can use to get pointers/values
- through the indirection.
- However you might not always need this.
- If you don't care about elements being "valid" you can use the fast iterator:
+ Internally the iterator is just struct {uint32_t major; uint32_t minor;}
+
+ Bucket array usage:
+
+ gs_bucket_array(float) ba = gs_bucket_array_new(float, 100); // Bucket array with internal 'float' data, where each bucket is 100 floats
+ gs_bucket_array_reserve(ba, 2); // Reserves 2 buckets
+ gs_bucket_array_push(ba, 3.145f); // Pushes 3.145 onto the end of the bucket array
+ float* val_p = gs_bucket_array_getp(ba, index); // Returns a pointer to your data
+ float val = gs_bucket_array_get(ba, index); // Dereferences your data as well
+
+ uint32_t bs = gs_bucket_array_bucket_size(ba) // Returns initialized bucket size
+ uint32_t bc = gs_bucket_array_bucket_count(ba) // Returns the amount of buckets allocated
+ uint32_t ba_cap = gs_bucket_array_capacity(ba) // Returns bucket_size * bucket_count
+ uint32_t ba_size = gs_bucket_array_size(ba) // returns index+1 of the last element
+ gs_bucket_array_free(ba) // Free's the entire array, make sure your own elements are free'd first
- for (
- gs_bucket_array_iter_fast it = gs_bucket_array_iter_fast_new(ba);
- gs_bucket_array_iter_fast_valid(ba, it);
- gs_bucket_array_iter_fast_advance(ba, it)
- ) {
- float v = gs_bucket_array_iter_fast_get(ba, it); // Get value using iterator
- float* vp = gs_bucket_array_iter_fast_getp(ba, it); // Get value pointer using iterator
- uint32_t hndl = gs_bucket_array_iter_fast_get_hndl(ba, it); // Get a normal handle from iterator
- }
- Internally the fast iterator is just struct {uint32_t major; uint32_t minor;}
- TIP:
- > You may store your own "bool enabled;" in what you store in the bucket array.
- > You can then use the fast iterator and check for this yourself.
- > However, note that this needs gs_bucket_array_new_ex where null_new_buckets is set to true,
- > this is because un-initialized data will otherwise cause problems.
+ Additionally, you may choose to use the provided bit field.
+ This allows usage of discarded slots, and iteration through just the valid elements.
+ The bit field uses compiler specific intrinsics (ffsll), and is not portable.
+ In the case where you use the bit field, you must NEVER use the following functions:
- Bucket Array Usage:
+ gs_bucket_array_push();
+ gs_bucket_array_reserve();
+
+ Instead use:
+
+ gs_bucket_array_bf_insert();
+ gs_bucket_array_bf_reserve();
+
+ Bucket array with bit field usage:
gs_bucket_array(float) ba = gs_bucket_array_new(float, 100); // Bucket array with internal 'float' data, where each bucket is 100 floats
- uint32_t hndl = gs_bucket_array_insert(ba, 3.145f); // Inserts your data into the bucket array, returns handle to you
- float* val_p = gs_bucket_array_getp(ba, hndl); // Returns your data to you using handle as lookup
- float val = gs_bucket_array_get(ba, hndl); // Dereferences your data as well
+ gs_bucket_array_bf_reserve(ba, 2); // Reserves 2 buckets
+ uitn32_t index = gs_bucket_array_bf_insert(ba, 3.145f); // Inserts 3.145 to some new or discarded place in ba
+ float* val_p = gs_bucket_array_getp(ba, index); // Returns a pointer to your data
+ float val = gs_bucket_array_get(ba, index); // Dereferences your data as well
+
uint32_t bs = gs_bucket_array_bucket_size(ba) // Returns initialized bucket size
uint32_t bc = gs_bucket_array_bucket_count(ba) // Returns the amount of buckets allocated
- uint32_t b_cap = gs_bucket_array_capacity(ba) // Returns bucket_size * bucket_count
- gs_bucket_array_clear(ba) // Sets the entire bit-field to 0
+ uint32_t ba_cap = gs_bucket_array_capacity(ba) // Returns bucket_size * bucket_count
+ uint32_t ba_size = gs_bucket_array_size(ba) // returns the same as capacity
+ gs_bucket_array_clear(ba) // invalidates all existing elements
gs_bucket_array_free(ba) // Free's the entire array, make sure your own elements are free'd first
- // if you use new_ex, you can set a bool to memset every new bucket to zero
- gs_bucket_array(int) ba_null_on_new = gs_bucket_array_new_ex(int, 64, true);
+ The bucket array with bit fields also has iterators:
+
+ for (
+ gs_bucket_array_bf_iter it = gs_bucket_array_iter_bf_new(ba);
+ gs_bucket_array_bf_iter_valid(ba, it);
+ gs_bucket_array_bf_iter_advance(ba, it)
+ ) {
+ float v = gs_bucket_array_get(ba, it); // Get value using iterator
+ float* vp = gs_bucket_array_getp(ba, it); // Get value pointer using iterator
+ }
*/
int main()
{
- gs_bucket_array(int) foo = gs_bucket_array_new_ex(int, 99, 1);
+ gs_bucket_array(int) foo = gs_bucket_array_new(int, 99);
gs_println("foo has a bucket size of %d", gs_bucket_array_bucket_size(foo));
+#ifdef GS_BUCKET_ARRAY_BIT_FIELD
+ gs_bucket_array_bf_reserve(foo, 2);
+#else // ! GS_BUCKET_ARRAY_BIT_FIELD
+ gs_bucket_array_reserve(foo, 2);
+#endif // GS_BUCKET_ARRAY_BIT_FIELD
+
uint32_t element_inserts = 400;
gs_println("---- inserting %d elements", element_inserts);
- for (int i = 0; i < element_inserts; i++)
-#if 0
- gs_println("got hndl %3d : bucket count %2d", gs_bucket_array_insert(foo, i), gs_bucket_array_bucket_count(foo));
-#else
- gs_bucket_array_insert(foo, i + 1);
-#endif
+ for (int i = 0; i < element_inserts; i++) {
+#ifdef GS_BUCKET_ARRAY_BIT_FIELD
+ gs_println("got hndl %3d for %3d : bucket count %2d", gs_bucket_array_bf_insert(foo, i), i, gs_bucket_array_bucket_count(foo));
+#else // ! GS_BUCKET_ARRAY_BIT_FIELD
+ gs_bucket_array_push(foo, i + 1);
+ gs_println("%3d has %3d : bucket count %2d", i, gs_bucket_array_get(foo, i), gs_bucket_array_bucket_count(foo));
+#endif // GS_BUCKET_ARRAY_BIT_FIELD
+ }
const int start = element_inserts + 5 - 20;
const int end = start + 20;
+
+
+#ifdef GS_BUCKET_ARRAY_BIT_FIELD
for (int i = start + 5; i < start + 10; i++)
- gs_bucket_array_erase(foo, i);
+ gs_bucket_array_bf_erase(foo, i);
gs_println("---- checking the elements %d -> %d", start, end);
for (int i = start; i < end; i++) {
- if (gs_bucket_array_exists(foo, i)) {
+ if (gs_bucket_array_bf_exists(foo, i)) {
gs_println("element %d: exists and has value %d", i, gs_bucket_array_get(foo, i));
} else {
gs_println("element %d: does not exist", i);
@@ -307,38 +408,43 @@ int main()
}
for (int i = 2; i < 100; i++)
- gs_bucket_array_erase(foo, i);
+ gs_bucket_array_bf_erase(foo, i);
+
int loops = 0;
- for (gs_bucket_array_iter it = gs_bucket_array_iter_new(foo);
- gs_bucket_array_iter_valid(foo, it);
- gs_bucket_array_iter_advance(foo, it)
+ for (gs_bucket_array_iter_bf it = gs_bucket_array_iter_bf_new(foo);
+ gs_bucket_array_iter_bf_valid(foo, it);
+ gs_bucket_array_iter_bf_advance(foo, it)
) {
int test = gs_bucket_array_get(foo, it);
int* testp = gs_bucket_array_getp(foo, it);
loops++;
- if (test == 250)
+ if (test == 250) {
gs_println("element with value 250 found after %d loops, iterator is now %d", loops, it);
+ break;
+ }
}
gs_bucket_array_clear(foo);
- for (gs_bucket_array_iter it = gs_bucket_array_iter_new(foo);
- gs_bucket_array_iter_valid(foo, it);
- gs_bucket_array_iter_advance(foo, it)
+ for (gs_bucket_array_iter_bf it = gs_bucket_array_iter_bf_new(foo);
+ gs_bucket_array_iter_bf_valid(foo, it);
+ gs_bucket_array_iter_bf_advance(foo, it)
) {
+ // will never print because of previous clear.
gs_println("element %d:%d", it, gs_bucket_array_get(foo, it));
}
+#endif // GS_BUCKET_ARRAY_BIT_FIELD
+
- for (gs_bucket_array_iter_fast it = gs_bucket_array_iter_fast_new(foo);
- gs_bucket_array_iter_fast_valid(foo, it);
- gs_bucket_array_iter_fast_advance(foo, it)
+
+ for (gs_bucket_array_iter it = gs_bucket_array_iter_new(foo);
+ gs_bucket_array_iter_valid(foo, it);
+ gs_bucket_array_iter_advance(foo, it)
) {
- int i = gs_bucket_array_iter_fast_get(foo, it);
- if (!i) break;
- uint32_t hndl = gs_bucket_array_iter_fast_get_hndl(foo, it);
+ int i = gs_bucket_array_iter_get(foo, it);
+ uint32_t hndl = gs_bucket_array_iter_get_hndl(foo, it);
gs_println("element %d:%d", hndl, i);
-
}
gs_bucket_array_free(foo);