diff options
| -rw-r--r-- | Makefile | 21 | ||||
| -rw-r--r-- | config.mk | 1 | ||||
| -rw-r--r-- | pk.h.in | 24 | ||||
| -rw-r--r-- | pkarr.h | 129 | ||||
| -rw-r--r-- | test/pkarr.c | 51 | ||||
| -rw-r--r-- | test/pkarr.cpp | 51 |
6 files changed, 275 insertions, 2 deletions
@@ -3,7 +3,7 @@ include config.mk -.PHONY: pkmacros pkmem-types pkmem pkstr +.PHONY: pkmacros pkmem-types pkmem pkstr pkarr SRC = \ pkmacros.h \ @@ -11,6 +11,7 @@ SRC = \ pkmem.h \ pkstr.h \ pkev.h \ + pkarr.h \ test/pkmacros.c \ test/pkmacros.cpp \ test/pkmem-types.c \ @@ -21,6 +22,7 @@ SRC = \ test/pkstr.cpp \ test/pkev.c \ test/pkev.cpp \ + test/pkarr.cpp \ OBJ = $(SRC:%.c=.o) PPOBJ = $(SRC:%.cpp=.so) @@ -33,10 +35,12 @@ all: options .WAIT clean .WAIT \ pkmem \ pkstr \ pkev \ + pkarr \ test-pkmem-types test-pkmem-types-cpp \ test-pkmem test-pkmem-cpp \ test-pkmacros test-pkmacros-cpp \ test-pkstr test-pkstr-cpp \ + test-pkarr test-pkarr-cpp \ options: @echo at-suite build options: @@ -70,11 +74,14 @@ pkstr: pkmacros pkstr.gch pkstr.gchpp pkev: pkev.gch pkev.gchpp +pkarr: pkarr.gch pkarr.gchpp + build: pkmacros build: pkmem-types build: pkmem build: pkstr build: pkev +build: pkarr echo "#ifndef PK_SINGLE_HEADER_FILE_H\n#define PK_SINGLE_HEADER_FILE_H" > pk.h cat pk.h.in \ pkmacros.h \ @@ -82,6 +89,7 @@ build: pkev pkmem.h \ pkstr.h \ pkev.h \ + pkarr.h \ >> pk.h echo "#endif /* PK_SINGLE_HEADER_FILE_H */" >> pk.h sed -i -r \ @@ -122,12 +130,19 @@ test-pkev: test/pkev.o test-pkev-cpp: test/pkev.so $(CXX) -g -O0 -std=c++23 $(CPPFLAGS) -o test/$@ $^ $(LDFLAGS) -test: pkmacros pkmem-types pkmem pkstr pkev +test-pkarr: test/pkarr.o + $(CC) -g -O0 -std=c2x $(CFLAGS) -o test/$@ $^ $(LDFLAGS) + +test-pkarr-cpp: test/pkarr.so + $(CXX) -g -O0 -std=c++23 $(CPPFLAGS) -o test/$@ $^ $(LDFLAGS) + +test: pkmacros pkmem-types pkmem pkstr pkev pkarr test: test-pkmacros test-pkmacros-cpp test: test-pkmem-types test-pkmem-types-cpp test: test-pkmem test-pkmem-cpp test: test-pkstr test-pkstr-cpp test: test-pkev test-pkev-cpp +test: test-pkarr test-pkarr-cpp test: @echo "" ./test/test-pkmacros ; echo Result: $$? "\n" @@ -140,6 +155,8 @@ test: ./test/test-pkstr-cpp ; echo Result: $$? "\n" ./test/test-pkev ; echo Result: $$? "\n" ./test/test-pkev-cpp ; echo Result: $$? "\n" + ./test/test-pkarr ; echo Result: $$? "\n" + ./test/test-pkarr-cpp ; echo Result: $$? "\n" clean: rm -f *.plist *.gch *.gchpp *.o *.so test/*.o test/*.so test/test-* @@ -20,6 +20,7 @@ SHARED_FLAGS = -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L \ -DPK_IMPL_MEM \ -DPK_IMPL_STR \ -DPK_IMPL_EV \ + -DPK_IMPL_ARR \ CPPFLAGS += -Wall $(INCS) $(SHARED_FLAGS) CFLAGS += -Wall $(INCS) $(SHARED_FLAGS) @@ -27,6 +27,7 @@ * # define PK_IMPL_MEM * # define PK_IMPL_STR * # define PK_IMPL_EV +* # define PK_IMPL_ARR * #include "pk.h" * ``` * @@ -119,6 +120,26 @@ * that in this provided scenario a given mgr will still grow if a second EV is * registered. * +******************************************************************************** +* pkarr.h: def PK_IMPL_ARR before including pk.h to enable ad-hoc +* +* Provides a structure for managing contiguous lists +* +* The following definitions (shown with defaults) can be overridden: +* PK_ARR_INITIAL_COUNT 16 +* PK_ARR_GROW_RATIO 1.5 +* +* Initialize `stride`, `alignment` (optional), and `bkt` (optional) members +* *before* calling any `pk_arr_*` methods. +* ``` c +* struct pk_arr arr = {0}; +* arr.stride = sizeof(obj); +* arr.alignment = alignof(obj); // optional +* arr.bkt = bkt; // optional +* pk_arr_reserve(&arr, 10); // optional +* pk_arr_append(&arr, &obj); +* ``` +* *******************************************************************************/ #define PK_VERSION "@@PK_VERSION@@" @@ -136,4 +157,7 @@ # ifndef PK_IMPL_EV # define PK_IMPL_EV # endif +# ifndef PK_IMPL_ARR +# define PK_IMPL_ARR +# endif #endif @@ -0,0 +1,129 @@ +#ifndef PK_PKARR_H +#define PK_PKARR_H + +#include <stdint.h> +#include "pkmem.h" /* delete me */ + +struct pk_arr { + uint32_t next; + uint32_t reserved; + uint32_t stride; + uint32_t alignment; + struct pk_membucket *bkt; + void *data; +}; + +void pk_arr_clear(struct pk_arr *arr); +void pk_arr_reset(struct pk_arr *arr); +void pk_arr_reserve(struct pk_arr *arr, uint32_t count); +void pk_arr_resize(struct pk_arr *arr, uint32_t count); +void pk_arr_move_to_back(struct pk_arr *arr, uint32_t index); +void pk_arr_append(struct pk_arr *arr, void *data); +void pk_arr_remove_at(struct pk_arr *arr, uint32_t index); + +#endif /* PK_PKARR_H */ +#ifdef PK_IMPL_ARR + +#ifndef PK_ARR_GROW_RATIO +#define PK_ARR_GROW_RATIO 1.5 +#endif +#ifndef PK_ARR_INITIAL_COUNT +#define PK_ARR_INITIAL_COUNT 16 +#endif + +void +pk_arr_clear(struct pk_arr *arr) +{ + arr->next = 0; +} + +void +pk_arr_reset(struct pk_arr *arr) +{ + arr->next = 0; + arr->reserved = 0; + if (arr->data != NULL) pk_delete(arr->data, arr->stride * arr->reserved, arr->bkt); + arr->data = NULL; +} + +void +pk_arr_reserve(struct pk_arr *arr, uint32_t count) +{ + if (arr->reserved >= count) return; + void *new_data = pk_new(arr->stride * count, arr->alignment, arr->bkt); + if (arr->data != NULL) { + memcpy(new_data, arr->data, arr->stride * arr->reserved); + pk_delete(arr->data, arr->stride * arr->reserved, arr->bkt); + } + arr->reserved = count; + arr->data = new_data; +} + +void +pk_arr_resize(struct pk_arr *arr, uint32_t count) +{ + pk_arr_reserve(arr, count); + arr->next = count; +} + +void +pk_arr_move_to_back(struct pk_arr *arr, uint32_t index) +{ + if (arr->reserved == 0) return; + if (arr->next <= 1) return; + char *new_data = (char *)pk_new(arr->stride * arr->reserved, arr->alignment, arr->bkt); + if (index > 0) { + memcpy(new_data, arr->data, arr->stride * index); + } + memcpy( + new_data + (arr->stride * (arr->next - 1)), + ((char *)arr->data) + (arr->stride * index), + arr->stride); + memcpy( + new_data + (arr->stride * index), + ((char *)arr->data) + (arr->stride * (index + 1)), + arr->stride * (arr->next - index - 1)); + pk_delete(arr->data, arr->stride * arr->reserved, arr->bkt); + arr->data = (void *)new_data; +} + +void +pk_arr_append(struct pk_arr *arr, void *data) +{ + if (arr->reserved == arr->next) { + uint32_t new_count = arr->reserved == 0 ? PK_ARR_INITIAL_COUNT : arr->reserved * PK_ARR_GROW_RATIO; + void *new_data = pk_new(arr->stride * new_count, arr->alignment, arr->bkt); + if (arr->data != NULL) { + memcpy(new_data, arr->data, arr->stride * arr->reserved); + pk_delete(arr->data, arr->stride * arr->reserved, arr->bkt); + } + arr->data = new_data; + arr->reserved = new_count; + } + memcpy(((char *)arr->data) + (arr->stride * arr->next), data, arr->stride); + arr->next += 1; + return; +} + +void +pk_arr_remove_at(struct pk_arr *arr, uint32_t index) +{ + if (arr->reserved == 0) return; + if (index == arr->next - 1) { + arr->next -=1; + return; + } + char *new_data = (char *)pk_new(arr->stride * arr->reserved, arr->alignment, arr->bkt); + if (index > 0) { + memcpy(new_data, arr->data, arr->stride * index); + } + memcpy( + new_data + (arr->stride * index), + ((char *)arr->data) + (arr->stride * (index + 1)), + arr->stride * (arr->next - index - 1)); + pk_delete(arr->data, arr->stride * arr->reserved, arr->bkt); + arr->data = (void *)new_data; + arr->next -= 1; +} + +#endif /* PK_IMPL_ARR */ diff --git a/test/pkarr.c b/test/pkarr.c new file mode 100644 index 0000000..d60d90c --- /dev/null +++ b/test/pkarr.c @@ -0,0 +1,51 @@ + +#include "../pkarr.h" + +void +test_spinup(struct pk_arr *arr, struct pk_membucket **bkt) +{ + memset(arr, 0, sizeof(struct pk_arr)); + *bkt = pk_bucket_create("test", 1024 * 1024, false); + arr->bkt = *bkt; +} + +void +test_teardown(struct pk_arr *arr, struct pk_membucket **bkt) +{ + pk_bucket_destroy(*bkt); + *bkt = NULL; + arr->data = NULL; +} + +int main(int argc, char *argv[]) +{ + (void)argc; + (void)argv; + struct pk_arr arr = {0}; + struct pk_membucket *bkt = {0}; + + /* template + { + test_spinup(&arr, &bkt); + + test_teardown(&arr, &bkt); + } + */ + + { + test_spinup(&arr, &bkt); + arr.stride = sizeof(uint8_t); + + uint8_t c = 255; + pk_arr_append(&arr, &c); + + if (arr.bkt == NULL) exit(1); + if (arr.data == NULL) exit(1); + if (arr.reserved == 0) exit(1); + if (arr.next != 1) exit(1); + + test_teardown(&arr, &bkt); + } + + return 0; +} diff --git a/test/pkarr.cpp b/test/pkarr.cpp new file mode 100644 index 0000000..d60d90c --- /dev/null +++ b/test/pkarr.cpp @@ -0,0 +1,51 @@ + +#include "../pkarr.h" + +void +test_spinup(struct pk_arr *arr, struct pk_membucket **bkt) +{ + memset(arr, 0, sizeof(struct pk_arr)); + *bkt = pk_bucket_create("test", 1024 * 1024, false); + arr->bkt = *bkt; +} + +void +test_teardown(struct pk_arr *arr, struct pk_membucket **bkt) +{ + pk_bucket_destroy(*bkt); + *bkt = NULL; + arr->data = NULL; +} + +int main(int argc, char *argv[]) +{ + (void)argc; + (void)argv; + struct pk_arr arr = {0}; + struct pk_membucket *bkt = {0}; + + /* template + { + test_spinup(&arr, &bkt); + + test_teardown(&arr, &bkt); + } + */ + + { + test_spinup(&arr, &bkt); + arr.stride = sizeof(uint8_t); + + uint8_t c = 255; + pk_arr_append(&arr, &c); + + if (arr.bkt == NULL) exit(1); + if (arr.data == NULL) exit(1); + if (arr.reserved == 0) exit(1); + if (arr.next != 1) exit(1); + + test_teardown(&arr, &bkt); + } + + return 0; +} |
