ソースを参照

Added an element destroyer function for DArray.

Aaro Saila 6 日 前
親
コミット
2344cac72d
3 ファイル変更、92 行追加、48 行削除
  1. 76 40
      include/scufcont/DArray.h
  2. 8 0
      meson.build
  3. 8 8
      tests/cmocka/DArray_tests.c

+ 76 - 40
include/scufcont/DArray.h

@@ -16,7 +16,7 @@
 
 #endif // SCUFCONT_BOUNDS_CHECK
 
-#define SCDARRAY_EXPANDER(macro, type, type_name, func_name) macro(type, SCDArray_##type_name, SCDArray_##type_name##_##func_name)
+#define SCDARRAY_EXPANDER(macro, type, type_name, func_name) macro(type, type_name, SCDArray_##type_name##_##func_name)
 
 #define SCDARRAY_IMPL(type, type_name)                                                  \
     SCDARRAY_EXPANDER(SCDARRAY_ALLOC, type, type_name, alloc)                           \
@@ -43,25 +43,41 @@
     SCDARRAY_EXPANDER(SCDARRAY_RESIZE_SIG, type, type_name, resize);                         \
     SCDARRAY_EXPANDER(SCDARRAY_REMOVE_SIG, type, type_name, remove);                         \
     SCDARRAY_EXPANDER(SCDARRAY_CLEAR_NO_RESIZE_SIG, type, type_name, clear_no_resize);       \
-    SCDARRAY_EXPANDER(SCDARRAY_CLEAR_SIG, type, type_name, clear);
+    SCDARRAY_EXPANDER(SCDARRAY_CLEAR_SIG, type, type_name, clear)
 
 #define SCDARRAY_HEADER(type, type_name) \
-    SCDARRAY_STRUCT(type, type_name)     \
+    SCDARRAY_DESTROYER(type, type_name); \
+    SCDARRAY_STRUCT(type, type_name);    \
     SCDARRAY_SIGS(type, type_name)
 
+// SCDARRAY_HEADER(char *, charp);
+
 // SCDARRAY_ALLOC_SIG(type, SCDArray_##type_name, SCDArray_##type_name##_alloc);
 // SCDARRAY_PUSH_BACK_SIG(type, SCDArray_##type_name, SCDArray_##type_name##_push_back);
 
-#define SCDARRAY_STRUCT(type, type_name) \
-    typedef struct {                     \
-        type *data;                      \
-        size_t len;                      \
-        size_t capacity;                 \
-    } SCDArray_##type_name;
+#define SCDARRAY_DESTROYER_FUNC_TYPE_NAME(type_name) SCDArray_##type_name##_destroyer_func
+
+#define SCDARRAY_DESTROYER(type, type_name) \
+    typedef void (*SCDARRAY_DESTROYER_FUNC_TYPE_NAME(type_name))(type *const elem)
+
+// SCDARRAY_DESTROYER(char *, charp);
 
-// SCDARRAY_STRUCT(int);
+#define SCDARRAY_STRUCT(type, type_name)             \
+    typedef struct {                                 \
+        type *data;                                  \
+        size_t len;                                  \
+        size_t capacity;                             \
+        SCDARRAY_DESTROYER_FUNC_TYPE_NAME(type_name) \
+        elem_destroy;                                \
+    } SCDArray_##type_name
 
-#define SCDARRAY_ALLOC_SIG(type, type_name, func_name) ScufContResult func_name(type_name *const darr)
+// SCDARRAY_STRUCT(char *, charp)
+
+#define SCDARRAY_ALLOC_SIG(type, type_name, func_name)            \
+    ScufContResult func_name(                                     \
+        SCDArray_##type_name *const darr,                         \
+        SCDARRAY_DESTROYER_FUNC_TYPE_NAME(type_name) elem_destroy \
+    )
 
 /**
   @fn SCDArray_alloc
@@ -77,10 +93,13 @@
         }                                              \
         darr->len = 0;                                 \
         darr->capacity = 1;                            \
+        darr->elem_destroy = elem_destroy;             \
         return SCUFCONT_SUCCESS;                       \
     }
 
-#define SCDARRAY_ALLOC_COPY_SIG(type, type_name, func_name) ScufContResult func_name(type_name *const dst, const type_name *const src)
+// SCDARRAY_ALLOC(char *, charp, SCDArray_charp_alloc)
+
+#define SCDARRAY_ALLOC_COPY_SIG(type, type_name, func_name) ScufContResult func_name(SCDArray_##type_name *const dst, const SCDArray_##type_name *const src)
 
 /**
   @fn SCDArray_alloc_copy
@@ -96,27 +115,34 @@
         }                                                         \
         dst->len = src->len;                                      \
         dst->capacity = src->capacity;                            \
+        dst->elem_destroy = src->elem_destroy;                    \
         memcpy(dst->data, src->data, src->len);                   \
         return SCUFCONT_SUCCESS;                                  \
     }
 
-#define SCDARRAY_FREE_SIG(type, type_name, func_name) void func_name(type_name *const darr)
+// SCDARRAY_ALLOC_COPY(char *, charp, SCDArray_charp_alloc_copy)
 
-#define SCDARRAY_FREE(type, type_name, func_name)   \
-    SCDARRAY_FREE_SIG(type, type_name, func_name) { \
-        free(darr->data);                           \
+#define SCDARRAY_FREE_SIG(type, type_name, func_name) void func_name(SCDArray_##type_name *const darr)
+
+#define SCDARRAY_FREE(type, type_name, func_name)                      \
+    SCDARRAY_FREE_SIG(type, type_name, func_name) {                    \
+        if (darr->elem_destroy != NULL) {                              \
+            for (size_t i = 0; i < darr->len; i++) {                   \
+                type *const elem = SCDArray_##type_name##_at(darr, i); \
+                darr->elem_destroy(elem);                              \
+            }                                                          \
+        }                                                              \
+        free(darr->data);                                              \
     }
 
-#define SCDARRAY_IS_NULL_SIG(type, type_name, func_name) bool func_name(const type_name *const darr)
+#define SCDARRAY_IS_NULL_SIG(type, type_name, func_name) bool func_name(const SCDArray_##type_name *const darr)
 
 #define SCDARRAY_IS_NULL(type, type_name, func_name)   \
     SCDARRAY_IS_NULL_SIG(type, type_name, func_name) { \
         return darr->data == NULL;                     \
     }
 
-// SCDARRAY_ALLOC(int, SCDArray_int, SCDArray_int_alloc);
-
-#define SCDARRAY_PUSH_BACK_SIG(type, type_name, func_name) ScufContResult func_name(type_name *const darr, const type *const new_elem)
+#define SCDARRAY_PUSH_BACK_SIG(type, type_name, func_name) ScufContResult func_name(SCDArray_##type_name *const darr, const type *const new_elem)
 
 /**
   @fn SCDArray_push_back
@@ -138,7 +164,7 @@
         return SCUFCONT_SUCCESS;                                                           \
     }
 
-#define SCDARRAY_PUSH_BACK_MULTIPLE_SIG(type, type_name, func_name) ScufContResult func_name(type_name *const darr, const type *const new_elems, const size_t new_elems_n)
+#define SCDARRAY_PUSH_BACK_MULTIPLE_SIG(type, type_name, func_name) ScufContResult func_name(SCDArray_##type_name *const darr, const type *const new_elems, const size_t new_elems_n)
 
 /**
   @fn SCDArray_push_back_multiple
@@ -162,7 +188,7 @@
 
 // SCDARRAY_PUSH_BACK_MULTIPLE(int, SCDArray_int, SCDArray_int_push_back_multiple)
 
-#define SCDARRAY_AT_SIG(type, type_name, func_name) type *func_name(const type_name *const darr, const size_t i)
+#define SCDARRAY_AT_SIG(type, type_name, func_name) type *func_name(const SCDArray_##type_name *const darr, const size_t i)
 
 // SCDARRAY_PUSH_BACK(int, SCDArray_int, SCDArray_int_push_back);
 
@@ -189,7 +215,7 @@
 
 // SCDARRAY_AT(char*, SCDArray_charp, SCDArray_charp_at)
 
-#define SCDARRAY_RESIZE_SIG(type, type_name, func_name) void func_name(type_name *const darr)
+#define SCDARRAY_RESIZE_SIG(type, type_name, func_name) void func_name(SCDArray_##type_name *const darr)
 
 #define SCDARRAY_RESIZE(type, type_name, func_name)                     \
     SCDARRAY_RESIZE_SIG(type, type_name, func_name) {                   \
@@ -200,10 +226,14 @@
         }                                                               \
     }
 
-#define SCDARRAY_REMOVE_NO_RESIZE_SIG(type, type_name, func_name) void func_name(type_name *const darr, const size_t i)
+#define SCDARRAY_REMOVE_NO_RESIZE_SIG(type, type_name, func_name) void func_name(SCDArray_##type_name *const darr, const size_t i)
 
 #define SCDARRAY_REMOVE_NO_RESIZE(type, type_name, func_name)                                  \
     SCDARRAY_REMOVE_SIG(type, type_name, func_name) {                                          \
+        if (darr->elem_destroy != NULL) {                                                      \
+            type *const elem = SCDArray_##type_name##_at(darr, i);                             \
+            darr->elem_destroy(elem);                                                          \
+        }                                                                                      \
         if (i != darr->len - 1) {                                                              \
             memmove(darr->data + i, darr->data + i + 1, (darr->len - (i + 1)) * sizeof(type)); \
         }                                                                                      \
@@ -212,31 +242,37 @@
 
 // SCDARRAY_EXPANDER(SCDARRAY_REMOVE_NO_RESIZE, char*, charp, remove_no_resize)
 
-#define SCDARRAY_REMOVE_SIG(type, type_name, func_name) void func_name(type_name *const darr, const size_t i)
+#define SCDARRAY_REMOVE_SIG(type, type_name, func_name) void func_name(SCDArray_##type_name *const darr, const size_t i)
 
-#define SCDARRAY_REMOVE(type, type_name, func_name)   \
-    SCDARRAY_REMOVE_SIG(type, type_name, func_name) { \
-        type_name##_remove_no_resize(darr, i);        \
-        type_name##_resize(darr);                     \
+#define SCDARRAY_REMOVE(type, type_name, func_name)       \
+    SCDARRAY_REMOVE_SIG(type, type_name, func_name) {     \
+        SCDArray_##type_name##_remove_no_resize(darr, i); \
+        SCDArray_##type_name##_resize(darr);              \
     }
 
 // SCDARRAY_EXPANDER(SCDARRAY_REMOVE, char*, charp, remove)
 
-#define SCDARRAY_CLEAR_NO_RESIZE_SIG(type, type_name, func_name) void func_name(type_name *const darr)
-
-#define SCDARRAY_CLEAR_NO_RESIZE(type, type_name, func_name)   \
-    SCDARRAY_CLEAR_NO_RESIZE_SIG(type, type_name, func_name) { \
-        darr->len = 0;                                         \
+#define SCDARRAY_CLEAR_NO_RESIZE_SIG(type, type_name, func_name) void func_name(SCDArray_##type_name *const darr)
+
+#define SCDARRAY_CLEAR_NO_RESIZE(type, type_name, func_name)           \
+    SCDARRAY_CLEAR_NO_RESIZE_SIG(type, type_name, func_name) {         \
+        if (darr->elem_destroy != NULL) {                              \
+            for (size_t i = 0; i < darr->len; i++) {                   \
+                type *const elem = SCDArray_##type_name##_at(darr, i); \
+                darr->elem_destroy(elem);                              \
+            }                                                          \
+        }                                                              \
+        darr->len = 0;                                                 \
     }
 
-// SCDARRAY_CLEAR_NO_RESIZE(char*, SCDArray_charp, SCDArray_charp_clear_no_resize)
+// SCDARRAY_CLEAR_NO_RESIZE(char*, charp, SCDArray_charp_clear_no_resize)
 
-#define SCDARRAY_CLEAR_SIG(type, type_name, func_name) void func_name(type_name *const darr)
+#define SCDARRAY_CLEAR_SIG(type, type_name, func_name) void func_name(SCDArray_##type_name *const darr)
 
-#define SCDARRAY_CLEAR(type, type_name, func_name)   \
-    SCDARRAY_CLEAR_SIG(type, type_name, func_name) { \
-        type_name##_clear_no_resize(darr);           \
-        type_name##_resize(darr);                    \
+#define SCDARRAY_CLEAR(type, type_name, func_name)    \
+    SCDARRAY_CLEAR_SIG(type, type_name, func_name) {  \
+        SCDArray_##type_name##_clear_no_resize(darr); \
+        SCDArray_##type_name##_resize(darr);          \
     }
 
 // SCDARRAY_EXPANDER(SCDARRAY_CLEAR, char*, charp, clear)

+ 8 - 0
meson.build

@@ -7,6 +7,8 @@ project(
   }
 )
 
+cc = meson.get_compiler('c')
+
 c_args = [
   '-std=c99',
   '-Wall',
@@ -49,3 +51,9 @@ if get_option('SCUFCONT_BUILD_TESTS') == true
   subdir('tests')
 endif
 
+darray_prepro = custom_target(
+  'DArray_prepro',
+  output: 'DArray_prepro.h',
+  input: 'include/scufcont/DArray.h',
+  command: [ cc.cmd_array(), c_args, '-E', '-o', '@OUTPUT@', '@INPUT@' ],
+)

+ 8 - 8
tests/cmocka/DArray_tests.c

@@ -5,14 +5,14 @@
 #include "scufcont/DArray.h"
 #include "scufcont/scufcont.h"
 
-SCDARRAY_HEADER(int, int)
+SCDARRAY_HEADER(int, int);
 SCDARRAY_IMPL(int, int)
 
 void test_DArray_alloc(void **state) {
     (void) state;
 
     SCDArray_int arr;
-    assert_true(SCDArray_int_alloc(&arr) == SCUFCONT_SUCCESS);
+    assert_true(SCDArray_int_alloc(&arr, NULL) == SCUFCONT_SUCCESS);
     assert_non_null(arr.data);
     assert_uint_equal(arr.len, 0u);
     assert_uint_equal(arr.capacity, 1u);
@@ -26,7 +26,7 @@ void test_DArray_alloc_copy(void **state) {
     srand(time(NULL));
 
     SCDArray_int arr;
-    assert_true(SCDArray_int_alloc(&arr) == SCUFCONT_SUCCESS);
+    assert_true(SCDArray_int_alloc(&arr, NULL) == SCUFCONT_SUCCESS);
 
     const size_t elems_n = rand() % 100;
     for (size_t i = 0; i < elems_n; i++) {
@@ -49,7 +49,7 @@ void test_DArray_push_back(void **state) {
     (void) state;
 
     SCDArray_int arr;
-    SCDArray_int_alloc(&arr);
+    SCDArray_int_alloc(&arr, NULL);
 
     assert_true(SCDArray_int_push_back(&arr, &(int) { 7 }) == SCUFCONT_SUCCESS);
     assert_true(arr.data[0] == 7);
@@ -65,7 +65,7 @@ void test_DArray_at(void **state) {
     (void) state;
 
     SCDArray_int arr;
-    SCDArray_int_alloc(&arr);
+    SCDArray_int_alloc(&arr, NULL);
 
     assert_true(SCDArray_int_push_back(&arr, &(int) { 7 }) == SCUFCONT_SUCCESS);
     assert_int_equal(*SCDArray_int_at(&arr, 0), 7);
@@ -81,7 +81,7 @@ void test_DArray_push_back_multiple(void **state) {
     (void) state;
 
     SCDArray_int arr;
-    SCDArray_int_alloc(&arr);
+    SCDArray_int_alloc(&arr, NULL);
 
     int nums[] = { 1, 2, 3, 4, 5 };
     const size_t nums_len = sizeof(nums) / sizeof(nums[0]);
@@ -106,7 +106,7 @@ void test_DArray_remove(void **state) {
     (void) state;
 
     SCDArray_int arr;
-    SCDArray_int_alloc(&arr);
+    SCDArray_int_alloc(&arr, NULL);
 
     int nums[] = { 1, 2, 3, 4, 5 };
     SCDArray_int_push_back_multiple(&arr, nums, sizeof(nums) / sizeof(nums[0]));
@@ -157,7 +157,7 @@ void test_DArray_clear(void **state) {
     (void) state;
 
     SCDArray_int arr;
-    SCDArray_int_alloc(&arr);
+    SCDArray_int_alloc(&arr, NULL);
 
     for (int i = 1; i <= 10; i++) {
         SCDArray_int_push_back(&arr, &i);