summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile21
-rw-r--r--config.mk1
-rw-r--r--pk.h.in24
-rw-r--r--pkarr.h129
-rw-r--r--test/pkarr.c51
-rw-r--r--test/pkarr.cpp51
6 files changed, 275 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index 681b36e..9d3c11f 100644
--- a/Makefile
+++ b/Makefile
@@ -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-*
diff --git a/config.mk b/config.mk
index a945eef..80bac5f 100644
--- a/config.mk
+++ b/config.mk
@@ -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)
diff --git a/pk.h.in b/pk.h.in
index e3af304..6ae6b89 100644
--- a/pk.h.in
+++ b/pk.h.in
@@ -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
diff --git a/pkarr.h b/pkarr.h
new file mode 100644
index 0000000..7da67fd
--- /dev/null
+++ b/pkarr.h
@@ -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;
+}