Added push_back_multiple, free, and remove to DArray. Added tests.

This commit is contained in:
2026-08-13 19:01:13 +03:00
parent 331529a05d
commit 6ce34dfe91
4 changed files with 197 additions and 25 deletions
+65 -24
View File
@@ -6,7 +6,7 @@
#include <stdlib.h> // IWYU pragma: keep #include <stdlib.h> // IWYU pragma: keep
#include <string.h> #include <string.h>
#include "scufcont.h" #include "scufcont.h" // IWYU pragma: keep
// #define SCUFCONT_BOUNDS_CHECK // #define SCUFCONT_BOUNDS_CHECK
@@ -18,21 +18,27 @@
#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, SCDArray_##type_name, SCDArray_##type_name##_##func_name)
#define SCDARRAY_IMPL(type, type_name) \ #define SCDARRAY_IMPL(type, type_name) \
SCDARRAY_EXPANDER(SCDARRAY_ALLOC, type, type_name, alloc) \ SCDARRAY_EXPANDER(SCDARRAY_ALLOC, type, type_name, alloc) \
SCDARRAY_EXPANDER(SCDARRAY_IS_NULL, type, type_name, is_null) \ SCDARRAY_EXPANDER(SCDARRAY_FREE, type, type_name, free) \
SCDARRAY_EXPANDER(SCDARRAY_PUSH_BACK, type, type_name, push_back) \ SCDARRAY_EXPANDER(SCDARRAY_IS_NULL, type, type_name, is_null) \
SCDARRAY_EXPANDER(SCDARRAY_AT, type, type_name, at) SCDARRAY_EXPANDER(SCDARRAY_PUSH_BACK, type, type_name, push_back) \
SCDARRAY_EXPANDER(SCDARRAY_PUSH_BACK_MULTIPLE, type, type_name, push_back_multiple) \
SCDARRAY_EXPANDER(SCDARRAY_AT, type, type_name, at) \
SCDARRAY_EXPANDER(SCDARRAY_REMOVE, type, type_name, remove)
#define SCDARRAY_HEADER(type, type_name) \ #define SCDARRAY_HEADER(type, type_name) \
SCDARRAY_STRUCT(type, type_name) \ SCDARRAY_STRUCT(type, type_name) \
SCDARRAY_SIGS(type, type_name) SCDARRAY_SIGS(type, type_name)
#define SCDARRAY_SIGS(type, type_name) \ #define SCDARRAY_SIGS(type, type_name) \
SCDARRAY_EXPANDER(SCDARRAY_ALLOC_SIG, type, type_name, alloc); \ SCDARRAY_EXPANDER(SCDARRAY_ALLOC_SIG, type, type_name, alloc); \
SCDARRAY_EXPANDER(SCDARRAY_IS_NULL_SIG, type, type_name, is_null); \ SCDARRAY_EXPANDER(SCDARRAY_FREE_SIG, type, type_name, free); \
SCDARRAY_EXPANDER(SCDARRAY_PUSH_BACK_SIG, type, type_name, push_back); \ SCDARRAY_EXPANDER(SCDARRAY_IS_NULL_SIG, type, type_name, is_null); \
SCDARRAY_EXPANDER(SCDARRAY_AT_SIG, type, type_name, at); SCDARRAY_EXPANDER(SCDARRAY_PUSH_BACK_SIG, type, type_name, push_back); \
SCDARRAY_EXPANDER(SCDARRAY_PUSH_BACK_MULTIPLE_SIG, type, type_name, push_back_multiple); \
SCDARRAY_EXPANDER(SCDARRAY_AT_SIG, type, type_name, at); \
SCDARRAY_EXPANDER(SCDARRAY_REMOVE_SIG, type, type_name, remove);
// SCDARRAY_ALLOC_SIG(type, SCDArray_##type_name, SCDArray_##type_name##_alloc); \ // SCDARRAY_ALLOC_SIG(type, SCDArray_##type_name, SCDArray_##type_name##_alloc); \
// SCDARRAY_PUSH_BACK_SIG(type, SCDArray_##type_name, SCDArray_##type_name##_push_back); // SCDARRAY_PUSH_BACK_SIG(type, SCDArray_##type_name, SCDArray_##type_name##_push_back);
@@ -59,6 +65,13 @@
return SCUFCONT_SUCCESS; \ return SCUFCONT_SUCCESS; \
} }
#define SCDARRAY_FREE_SIG(type, type_name, func_name) void func_name(type_name* darr)
#define SCDARRAY_FREE(type, type_name, func_name) \
SCDARRAY_FREE_SIG(type, type_name, func_name) { \
free(darr->data); \
}
#define SCDARRAY_IS_NULL_SIG(type, type_name, func_name) bool func_name(const type_name* darr) #define SCDARRAY_IS_NULL_SIG(type, type_name, func_name) bool func_name(const type_name* darr)
#define SCDARRAY_IS_NULL(type, type_name, func_name) \ #define SCDARRAY_IS_NULL(type, type_name, func_name) \
@@ -68,22 +81,40 @@
// SCDARRAY_ALLOC(int, SCDArray_int, SCDArray_int_alloc); // SCDARRAY_ALLOC(int, SCDArray_int, SCDArray_int_alloc);
#define SCDARRAY_PUSH_BACK_SIG(type, type_name, func_name) int func_name(type_name* darr, const type* new_elem) #define SCDARRAY_PUSH_BACK_SIG(type, type_name, func_name) ScufContResult func_name(type_name* darr, const type* new_elem)
#define SCDARRAY_PUSH_BACK(type, type_name, func_name) \ #define SCDARRAY_PUSH_BACK(type, type_name, func_name) \
SCDARRAY_PUSH_BACK_SIG(type, type_name, func_name) { \ SCDARRAY_PUSH_BACK_SIG(type, type_name, func_name) { \
if (darr->len + 1 > darr->capacity) { \ if (darr->len + 1 > darr->capacity) { \
darr->capacity *= 2; \ darr->capacity *= 2; \
darr->data = (type*) realloc(darr->data, darr->capacity * sizeof(type)); \ darr->data = (type*) realloc(darr->data, darr->capacity * sizeof(*new_elem)); \
if (darr->data == NULL) { \ if (darr->data == NULL) { \
return -1; \ return SCUFCONT_OUT_OF_MEMORY; \
} \ } \
} \ } \
memcpy(darr->data + darr->len, new_elem, sizeof(type)); \ memcpy(darr->data + darr->len, new_elem, sizeof(*new_elem)); \
darr->len++; \ darr->len++; \
return 1; \ return SCUFCONT_SUCCESS; \
} }
#define SCDARRAY_PUSH_BACK_MULTIPLE_SIG(type, type_name, func_name) ScufContResult func_name(type_name* darr, const type* new_elems, const size_t new_elems_n)
#define SCDARRAY_PUSH_BACK_MULTIPLE(type, type_name, func_name) \
SCDARRAY_PUSH_BACK_MULTIPLE_SIG(type, type_name, func_name) { \
if (darr->len + new_elems_n > darr->capacity) { \
darr->data = (type*) realloc(darr->data, (darr->capacity + new_elems_n) * sizeof(type)); \
if (darr->data == NULL) { \
return SCUFCONT_OUT_OF_MEMORY; \
} \
darr->capacity += new_elems_n; \
} \
memcpy(darr->data + darr->len, new_elems, sizeof(type) * new_elems_n); \
darr->len += new_elems_n; \
return SCUFCONT_SUCCESS; \
}
// SCDARRAY_PUSH_BACK_MULTIPLE(int, SCDArray_int, SCDArray_int_push_back_multiple)
#define SCDARRAY_AT_SIG(type, type_name, func_name) type* func_name(type_name* darr, const size_t i) #define SCDARRAY_AT_SIG(type, type_name, func_name) type* func_name(type_name* darr, const size_t i)
// SCDARRAY_PUSH_BACK(int, SCDArray_int, SCDArray_int_push_back); // SCDARRAY_PUSH_BACK(int, SCDArray_int, SCDArray_int_push_back);
@@ -111,4 +142,14 @@
// SCDARRAY_AT(char*, SCDArray_charp, SCDArray_charp_at) // SCDARRAY_AT(char*, SCDArray_charp, SCDArray_charp_at)
#define SCDARRAY_REMOVE_SIG(type, type_name, func_name) void func_name(type_name* darr, const size_t i)
#define SCDARRAY_REMOVE(type, type_name, func_name) \
SCDARRAY_REMOVE_SIG(type, type_name, func_name) { \
memmove(darr->data + i, darr->data + i + 1, (darr->len - i) * sizeof(type)); \
darr->len--; \
}
// SCDARRAY_REMOVE(char*, SCDArray_charp, SCDArray_charp_remove)
#endif // SCUFCONT_DARRAY_H_ #endif // SCUFCONT_DARRAY_H_
+123 -1
View File
@@ -1,11 +1,12 @@
#include <cmocka.h> #include <cmocka.h>
#include "DArray.h" #include "DArray.h"
#include "scufcont.h"
SCDARRAY_HEADER(int, int) SCDARRAY_HEADER(int, int)
SCDARRAY_IMPL(int, int) SCDARRAY_IMPL(int, int)
void DArray_alloc_test(void** state) { void test_DArray_alloc(void** state) {
(void) state; (void) state;
SCDArray_int arr; SCDArray_int arr;
@@ -13,5 +14,126 @@ void DArray_alloc_test(void** state) {
assert_non_null(arr.data); assert_non_null(arr.data);
assert_uint_equal(arr.len, 0u); assert_uint_equal(arr.len, 0u);
assert_uint_equal(arr.capacity, 1u); assert_uint_equal(arr.capacity, 1u);
SCDArray_int_free(&arr);
} }
void test_DArray_push_back(void** state) {
(void) state;
SCDArray_int arr;
SCDArray_int_alloc(&arr);
assert_true(SCDArray_int_push_back(&arr, &(int){7}) == SCUFCONT_SUCCESS);
assert_true(arr.data[0] == 7);
assert_true(SCDArray_int_push_back(&arr, &(int){10}) == SCUFCONT_SUCCESS);
assert_true(arr.data[0] == 7);
assert_true(arr.data[1] == 10);
SCDArray_int_free(&arr);
}
void test_DArray_at(void** state) {
(void) state;
SCDArray_int arr;
SCDArray_int_alloc(&arr);
assert_true(SCDArray_int_push_back(&arr, &(int){7}) == SCUFCONT_SUCCESS);
assert_int_equal(*SCDArray_int_at(&arr, 0), 7);
assert_true(SCDArray_int_push_back(&arr, &(int){10}) == SCUFCONT_SUCCESS);
assert_int_equal(*SCDArray_int_at(&arr, 0), 7);
assert_int_equal(*SCDArray_int_at(&arr, 1), 10);
SCDArray_int_free(&arr);
}
void test_DArray_push_back_multiple(void** state) {
(void) state;
SCDArray_int arr;
SCDArray_int_alloc(&arr);
int nums[] = { 1, 2, 3, 4, 5 };
const size_t nums_len = sizeof(nums) / sizeof(nums[0]);
assert_true(SCDArray_int_push_back_multiple(&arr, nums, sizeof(nums) / sizeof(nums[0])) == SCUFCONT_SUCCESS);
for (size_t i = 0; i < arr.len; i++) {
assert_int_equal(*SCDArray_int_at(&arr, i), nums[i]);
}
int nums2[] = { 6, 7, 8 };
const size_t nums2_len = sizeof(nums2) / sizeof(nums2[0]);
assert_true(SCDArray_int_push_back_multiple(&arr, nums2, sizeof(nums2) / sizeof(nums2[0])) == SCUFCONT_SUCCESS);
for (size_t i = 0; i < nums_len; i++) {
assert_int_equal(*SCDArray_int_at(&arr, i), nums[i]);
}
for (size_t i = 0; i < nums2_len; i++) {
assert_int_equal(*SCDArray_int_at(&arr, i + nums_len), nums2[i]);
}
SCDArray_int_free(&arr);
}
void test_DArray_remove(void** state) {
(void) state;
SCDArray_int arr;
SCDArray_int_alloc(&arr);
int nums[] = { 1, 2, 3, 4, 5 };
SCDArray_int_push_back_multiple(&arr, nums, sizeof(nums) / sizeof(nums[0]));
for (size_t i = 0; i < arr.len; i++) {
assert_int_equal(*SCDArray_int_at(&arr, i), nums[i]);
}
// Remove last
{
const size_t old_len = arr.len;
SCDArray_int_remove(&arr, arr.len - 1);
assert_uint_equal(arr.len, old_len - 1);
int new_nums[] = { 1, 2, 3, 4 };
assert_uint_equal(arr.len, sizeof(new_nums) / sizeof(new_nums[0]));
for (size_t i = 0; i < arr.len; i++) {
assert_int_equal(*SCDArray_int_at(&arr, i), new_nums[i]);
}
}
// Remove from middle
{
const size_t old_len = arr.len;
SCDArray_int_remove(&arr, 1);
assert_uint_equal(arr.len, old_len - 1);
int new_nums[] = { 1, 3, 4 };
assert_uint_equal(arr.len, sizeof(new_nums) / sizeof(new_nums[0]));
for (size_t i = 0; i < arr.len; i++) {
assert_int_equal(*SCDArray_int_at(&arr, i), new_nums[i]);
}
}
// Remove first
{
const size_t old_len = arr.len;
SCDArray_int_remove(&arr, 0);
assert_uint_equal(arr.len, old_len - 1);
int new_nums[] = { 3, 4 };
assert_uint_equal(arr.len, sizeof(new_nums) / sizeof(new_nums[0]));
for (size_t i = 0; i < arr.len; i++) {
assert_int_equal(*SCDArray_int_at(&arr, i), new_nums[i]);
}
}
SCDArray_int_free(&arr);
}
int DArray_tests_run(void) {
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_DArray_alloc),
cmocka_unit_test(test_DArray_push_back),
cmocka_unit_test(test_DArray_at),
cmocka_unit_test(test_DArray_push_back_multiple),
cmocka_unit_test(test_DArray_remove),
};
return cmocka_run_group_tests_name("DArray", tests, NULL, NULL);
}
+8
View File
@@ -1,11 +1,19 @@
#include <cmocka.h> #include <cmocka.h>
int DString_tests_run(void); int DString_tests_run(void);
int DArray_tests_run(void);
int main(void) { int main(void) {
int failed = 0; int failed = 0;
failed = DString_tests_run(); failed = DString_tests_run();
if (failed) {
return failed;
}
failed = DArray_tests_run();
if (failed) {
return failed;
}
return failed; return failed;
} }
+1
View File
@@ -1,5 +1,6 @@
cmocka_tests = executable( cmocka_tests = executable(
'cmocka_tests', 'cmocka_tests',
'DArray_tests.c',
'DString_tests.c', 'DString_tests.c',
'main.c', 'main.c',
include_directories: [ include_directories: [