diff --git a/src/dynamic_array.h b/src/dynamic_array.h index 764b328..a2a937e 100644 --- a/src/dynamic_array.h +++ b/src/dynamic_array.h @@ -23,51 +23,75 @@ typedef struct { } ArrayHeader; -#define array_create(arr) \ - do { \ - ArrayHeader *header = malloc(sizeof(*arr) * DYNAMIC_ARRAY_DEFAULT_ARRAY_SIZE + sizeof(ArrayHeader)); \ - header->size = 0; \ - header->capacity = DYNAMIC_ARRAY_DEFAULT_ARRAY_SIZE; \ - \ - arr = (void *)(header + 1); \ +#define array_create(arr) \ + do { \ + ArrayHeader *header = malloc( \ + sizeof(*(arr)) * DYNAMIC_ARRAY_DEFAULT_ARRAY_SIZE + sizeof(ArrayHeader) \ + ); \ + if (header == NULL) { \ + abort(); \ + } \ + header->size = 0; \ + header->capacity = DYNAMIC_ARRAY_DEFAULT_ARRAY_SIZE; \ + \ + (arr) = (void *)(header + 1); \ } while(0) -#define array_get_header(arr) ((ArrayHeader*)(arr) - 1) +#define array_get_header(arr) \ + ((arr) ? ((ArrayHeader*)(arr) - 1) : NULL) -#define array_destroy(arr) \ - do { \ - free(array_get_header(arr)); \ - arr = NULL; \ +#define array_destroy(arr) \ + do { \ + if ((arr) == NULL) { \ + break; \ + } \ + free(array_get_header(arr)); \ + (arr) = NULL; \ } while (0) -#define array_push_value(arr, value) \ - do { \ - ArrayHeader *header = array_get_header(arr); \ - if (header->size + 1 > header->capacity) { \ - size_t new_capacity = header->capacity * DYNAMIC_ARRAY_CAPACITY_FACTOR; \ - ArrayHeader *new_header = realloc(header, sizeof(*arr) * new_capacity + sizeof(ArrayHeader)); \ - if (new_header != NULL) { \ - header = new_header; \ - } \ - header->capacity = new_capacity; \ - arr = (void *)(header + 1); \ - } \ - arr[header->size] = value; \ - header->size++; \ +#define array_push_value(arr, value) \ + do { \ + if ((arr) == NULL) { \ + array_create(arr); \ + } \ + ArrayHeader *header = array_get_header(arr); \ + if (header->size >= header->capacity) { \ + size_t new_capacity = header->capacity * DYNAMIC_ARRAY_CAPACITY_FACTOR; \ + ArrayHeader *new_header = realloc( \ + header, sizeof(*(arr)) * new_capacity + sizeof(ArrayHeader) \ + ); \ + if (new_header == NULL) { \ + abort(); \ + } \ + header = new_header; \ + header->capacity = new_capacity; \ + (arr) = (void *)(header + 1); \ + } \ + (arr)[header->size] = (value); \ + header->size++; \ } while (0) -#define array_pop(arr) \ - do { \ - ArrayHeader *header = array_get_header(arr); \ - if (header->size == 0) { \ - break; \ - } \ - header->size--; \ +#define array_pop(arr) \ + do { \ + if ((arr) == NULL) { \ + break; \ + } \ + ArrayHeader *header = array_get_header(arr); \ + if (header->size == 0) { \ + break; \ + } \ + header->size--; \ } while (0) +#define array_size(arr) \ + ((arr) ? array_get_header(arr)->size : 0) + +#define array_capacity(arr) \ + ((arr) ? array_get_header(arr)->capacity : 0) + #endif \ No newline at end of file diff --git a/src/test_dynamic_array.c b/src/test_dynamic_array.c index de49963..77b955e 100644 --- a/src/test_dynamic_array.c +++ b/src/test_dynamic_array.c @@ -178,6 +178,74 @@ void test_array_looping(void) { } +/* --- array_get_header branch: NULL arr → returns NULL --- */ +void test_array_get_header_on_null_returns_null(void) { + int *arr = NULL; + TEST_ASSERT_NULL(array_get_header(arr)); +} + + +/* --- array_destroy branch: NULL arr → no-op, does not crash --- */ +void test_array_destroy_on_null_is_noop(void) { + int *arr = NULL; + array_destroy(arr); + TEST_ASSERT_NULL(arr); +} + + +/* --- array_push_value branch: NULL arr → auto-creates the array --- */ +void test_array_push_value_on_null_auto_creates(void) { + int *arr = NULL; + array_push_value(arr, 7); + TEST_ASSERT_NOT_NULL(arr); + TEST_ASSERT_EQUAL(7, arr[0]); + TEST_ASSERT_EQUAL(1, array_get_header(arr)->size); + array_destroy(arr); +} + + +/* --- array_pop branch: NULL arr → no-op, does not crash --- */ +void test_array_pop_on_null_is_noop(void) { + int *arr = NULL; + array_pop(arr); + TEST_ASSERT_NULL(arr); +} + + +/* --- array_size branch: NULL arr → 0 --- */ +void test_array_size_on_null_returns_zero(void) { + int *arr = NULL; + TEST_ASSERT_EQUAL(0, array_size(arr)); +} + + +/* --- array_size branch: non-NULL arr → current size --- */ +void test_array_size_returns_current_size(void) { + int *arr = NULL; + array_create(arr); + array_push_value(arr, 1); + array_push_value(arr, 2); + TEST_ASSERT_EQUAL(2, array_size(arr)); + array_destroy(arr); +} + + +/* --- array_capacity branch: NULL arr → 0 --- */ +void test_array_capacity_on_null_returns_zero(void) { + int *arr = NULL; + TEST_ASSERT_EQUAL(0, array_capacity(arr)); +} + + +/* --- array_capacity branch: non-NULL arr → current capacity --- */ +void test_array_capacity_returns_current_capacity(void) { + int *arr = NULL; + array_create(arr); + TEST_ASSERT_EQUAL(DYNAMIC_ARRAY_DEFAULT_ARRAY_SIZE, array_capacity(arr)); + array_destroy(arr); +} + + int main(void) { UNITY_BEGIN(); @@ -195,5 +263,14 @@ int main(void) RUN_TEST(test_array_values_correct_after_growth); RUN_TEST(test_array_looping); + RUN_TEST(test_array_get_header_on_null_returns_null); + RUN_TEST(test_array_destroy_on_null_is_noop); + RUN_TEST(test_array_push_value_on_null_auto_creates); + RUN_TEST(test_array_pop_on_null_is_noop); + RUN_TEST(test_array_size_on_null_returns_zero); + RUN_TEST(test_array_size_returns_current_size); + RUN_TEST(test_array_capacity_on_null_returns_zero); + RUN_TEST(test_array_capacity_returns_current_capacity); + return UNITY_END(); } \ No newline at end of file