aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2020-12-05 16:03:09 -0700
committerJosh Rahm <joshuarahm@gmail.com>2020-12-05 16:03:09 -0700
commit23fe71639ecdc20a472130de6a2b8d71d8e5d2b0 (patch)
tree701e444f668d2458234bea38962226d90bb26e9f
parentde81911ef4c15a9518acf32f61ad2d7d0e2f156f (diff)
downloadstm32l4-23fe71639ecdc20a472130de6a2b8d71d8e5d2b0.tar.gz
stm32l4-23fe71639ecdc20a472130de6a2b8d71d8e5d2b0.tar.bz2
stm32l4-23fe71639ecdc20a472130de6a2b8d71d8e5d2b0.zip
Add array_list.h
-rw-r--r--include/shared/array_list.h105
-rw-r--r--tests/test_array_list.c65
2 files changed, 170 insertions, 0 deletions
diff --git a/include/shared/array_list.h b/include/shared/array_list.h
new file mode 100644
index 0000000..8b942ad
--- /dev/null
+++ b/include/shared/array_list.h
@@ -0,0 +1,105 @@
+#ifndef SHARED_ARRAY_LIST_H_
+#define SHARED_ARRAY_LIST_H_
+
+#include "kern/common.h"
+#include "kern/mem.h"
+
+#define ALLOC kalloc
+#define FREE kfree
+
+#define array_list_t(type) array_list_##type##_t
+#define array_list_new(type) array_list_##type##_new
+#define array_list_length(type) array_list_##type##_length
+#define array_list_reserve(type) array_list_##type##_reserve
+#define array_list_add(type) array_list_##type##_add
+#define array_list_remove(type) array_list_##type##remove
+#define array_list_ref(type) array_list_##type##_get
+#define array_list_free(type) array_list_##type##_free
+
+#define array_list_foreach(ar, val) \
+ typeof((ar)->elements[0]) val; \
+ if ((ar)->size > 0) val = (ar)->elements[0]; \
+ for (size_t _idx_ = 0; _idx_ < (ar)->size; \
+ val = (++_idx_) >= (ar)->size ? val : (ar)->elements[_idx_])
+
+#define ARRAY_LIST_DECL(type) \
+ typedef struct { \
+ size_t reserved; \
+ size_t size; \
+ type* elements; \
+ } array_list_t(type); \
+ size_t array_list_length(type)(const array_list_t(type)*); \
+ array_list_t(type) * array_list_new(type)(); \
+ bool array_list_reserve(type)(array_list_t(type)*, size_t len); \
+ bool array_list_add(type)(array_list_t(type)*, type val); \
+ bool array_list_remove(type)(array_list_t(type)*, size_t idx, type * out); \
+ type* array_list_ref(type)(array_list_t(type)*, size_t idx); \
+ void array_list_free(type)(array_list_t(type)*);
+
+#define ARRAY_LIST_IMPL(type) \
+ array_list_t(type) * array_list_new(type)() \
+ { \
+ array_list_t(type)* ret = ALLOC(sizeof(array_list_t(type))); \
+ ret->size = 0; \
+ ret->reserved = 0; \
+ ret->elements = NULL; \
+ return ret; \
+ } \
+ size_t array_list_length(type)(const array_list_t(type) * lst) \
+ { \
+ return lst->size; \
+ } \
+ bool array_list_reserve(type)(array_list_t(type) * lst, size_t newlen) \
+ { \
+ if (lst->reserved < newlen) { \
+ type* new_arr = ALLOC(sizeof(type) * newlen); \
+ if (!new_arr) { \
+ return 0; \
+ } \
+ for (size_t i = 0; i < lst->size; ++i) { \
+ new_arr[i] = lst->elements[i]; \
+ } \
+ FREE(lst->elements); \
+ lst->elements = new_arr; \
+ lst->reserved = newlen; \
+ } \
+ return 1; \
+ } \
+ bool array_list_add(type)(array_list_t(type) * lst, type v) \
+ { \
+ if (lst->size == lst->reserved) { \
+ if (!array_list_reserve(type)( \
+ lst, lst->reserved == 0 ? 4 : lst->reserved * 2)) { \
+ return 0; \
+ } \
+ } \
+ lst->elements[lst->size++] = v; \
+ return 1; \
+ } \
+ bool array_list_remove(type)( \
+ array_list_t(type) * lst, size_t idx, type * out) \
+ { \
+ if (idx >= lst->size) { \
+ return 0; \
+ } \
+ if (out) *out = lst->elements[idx]; \
+ for (size_t i = idx; i < lst->size - 1; ++i) { \
+ lst->elements[i] = lst->elements[i + 1]; \
+ } \
+ lst->size--; \
+ return 1; \
+ } \
+ type* array_list_ref(type)(array_list_t(type) * lst, size_t idx) \
+ { \
+ if (idx >= lst->size) { \
+ return NULL; \
+ } \
+ return &lst->elements[idx]; \
+ } \
+ void array_list_free(type)(array_list_t(type) * lst) \
+ { \
+ FREE(lst->elements); \
+ FREE(lst); \
+ }
+
+#endif /* SHARED_ARRAY_LIST_H_ */
diff --git a/tests/test_array_list.c b/tests/test_array_list.c
new file mode 100644
index 0000000..71ffa55
--- /dev/null
+++ b/tests/test_array_list.c
@@ -0,0 +1,65 @@
+#include "kern/mem.h"
+#include "shared/array_list.h"
+#include "test_harness.h"
+
+ARRAY_LIST_DECL(int);
+ARRAY_LIST_IMPL(int);
+
+TEST(array_list, smell)
+{
+ array_list_t(int)* list = array_list_new(int)();
+
+ array_list_add(int)(list, 1);
+ array_list_add(int)(list, 2);
+ array_list_add(int)(list, 3);
+ array_list_add(int)(list, 4);
+ array_list_add(int)(list, 5);
+
+ int expected[5] = {1, 2, 3, 4, 5};
+
+ for (size_t i = 0; i < 5; ++i) {
+ ASSERT_EQ(*array_list_ref(int)(list, i), expected[i]);
+ }
+
+ ASSERT_EQ(array_list_length(int)(list), 5);
+ *array_list_ref(int)(list, 3) = 8;
+ expected[3] = 8;
+
+ for (size_t i = 0; i < 5; ++i) {
+ ASSERT_EQ(*array_list_ref(int)(list, i), expected[i]);
+ }
+
+ int out;
+ array_list_remove(int)(list, 2, &out);
+ ASSERT_EQ(out, 3);
+ ASSERT_EQ(array_list_length(int)(list), 4);
+
+ int expected2[4] = {1, 2, 8, 5};
+ for (size_t i = 0; i < 4; ++i) {
+ ASSERT_EQ(*array_list_ref(int)(list, i), expected2[i]);
+ }
+
+ return 0;
+}
+
+TEST(array_list, foreach)
+{
+ array_list_t(int)* arl = array_list_new(int)();
+ array_list_add(int)(arl, 3);
+ array_list_add(int)(arl, 2);
+ array_list_add(int)(arl, 1);
+
+ int i = 0;
+ int values[3];
+ array_list_foreach(arl, val) {
+ values[i] = val;
+ ++ i;
+ }
+
+ ASSERT_EQ(values[0], 3);
+ ASSERT_EQ(values[1], 2);
+ ASSERT_EQ(values[2], 1);
+
+ return 0;
+
+}