Compare commits
6 Commits
8c6e7e035b
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
4238d73749
|
|||
|
a8cd5fb7a8
|
|||
|
09e1a360fd
|
|||
| 60f9f88af2 | |||
|
e5e4d75e2c
|
|||
|
10251039d5
|
@@ -6,7 +6,7 @@ UseTab: Never
|
|||||||
|
|
||||||
ColumnLimit: 100
|
ColumnLimit: 100
|
||||||
|
|
||||||
BreakBeforeBraces: Allman
|
BreakBeforeBraces: Attach
|
||||||
|
|
||||||
AllowShortIfStatementsOnASingleLine: false
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
AllowShortFunctionsOnASingleLine: None
|
AllowShortFunctionsOnASingleLine: None
|
||||||
@@ -19,4 +19,4 @@ SortIncludes: true
|
|||||||
|
|
||||||
IndentCaseLabels: true
|
IndentCaseLabels: true
|
||||||
|
|
||||||
AlignEscapedNewlines: Left
|
AlignEscapedNewlines: Right
|
||||||
|
|||||||
@@ -4,7 +4,9 @@
|
|||||||
#define DYNAMIC_ARRAY_VERSION_MAJOR 0
|
#define DYNAMIC_ARRAY_VERSION_MAJOR 0
|
||||||
#define DYNAMIC_ARRAY_VERSION_MINOR 1
|
#define DYNAMIC_ARRAY_VERSION_MINOR 1
|
||||||
#define DYNAMIC_ARRAY_VERSION_BUILD 0
|
#define DYNAMIC_ARRAY_VERSION_BUILD 0
|
||||||
#define DYNAMIC_ARRAY_VERSION ((DYNAMIC_ARRAY_VERSION_MAJOR << 16) | (DYNAMIC_ARRAY_VERSION_MINOR << 8) | DYNAMIC_ARRAY_VERSION_BUILD)
|
#define DYNAMIC_ARRAY_VERSION \
|
||||||
|
((DYNAMIC_ARRAY_VERSION_MAJOR << 16) | (DYNAMIC_ARRAY_VERSION_MINOR << 8) | \
|
||||||
|
DYNAMIC_ARRAY_VERSION_BUILD)
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -12,8 +14,6 @@
|
|||||||
#define DYNAMIC_ARRAY_DEFAULT_ARRAY_SIZE 10
|
#define DYNAMIC_ARRAY_DEFAULT_ARRAY_SIZE 10
|
||||||
#define DYNAMIC_ARRAY_CAPACITY_FACTOR 2
|
#define DYNAMIC_ARRAY_CAPACITY_FACTOR 2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// [ HEADER | ARRAY ELEMENTS ]
|
// [ HEADER | ARRAY ELEMENTS ]
|
||||||
// ↑
|
// ↑
|
||||||
// THIS IS THE POINTER RETURNED BY ALL MACROS
|
// THIS IS THE POINTER RETURNED BY ALL MACROS
|
||||||
@@ -22,49 +22,65 @@ typedef struct {
|
|||||||
size_t capacity;
|
size_t capacity;
|
||||||
} ArrayHeader;
|
} ArrayHeader;
|
||||||
|
|
||||||
|
|
||||||
#define array_create(arr) \
|
#define array_create(arr) \
|
||||||
do { \
|
do { \
|
||||||
ArrayHeader *header = malloc(sizeof(*arr) * DYNAMIC_ARRAY_DEFAULT_ARRAY_SIZE + sizeof(ArrayHeader)); \
|
ArrayHeader* header = \
|
||||||
|
malloc(sizeof(*(arr)) * DYNAMIC_ARRAY_DEFAULT_ARRAY_SIZE + sizeof(ArrayHeader)); \
|
||||||
|
if (header == NULL) { \
|
||||||
|
abort(); \
|
||||||
|
} \
|
||||||
header->size = 0; \
|
header->size = 0; \
|
||||||
header->capacity = DYNAMIC_ARRAY_DEFAULT_ARRAY_SIZE; \
|
header->capacity = DYNAMIC_ARRAY_DEFAULT_ARRAY_SIZE; \
|
||||||
\
|
\
|
||||||
arr = (void *)(header + 1); \
|
(arr) = (void*)(header + 1); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define array_get_header(arr) ((arr) ? ((ArrayHeader*)(arr) - 1) : NULL)
|
||||||
#define array_get_header(arr) ((ArrayHeader*)(arr) - 1)
|
|
||||||
|
|
||||||
|
|
||||||
#define array_destroy(arr) \
|
#define array_destroy(arr) \
|
||||||
do { \
|
do { \
|
||||||
|
if ((arr) == NULL) { \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
free(array_get_header(arr)); \
|
free(array_get_header(arr)); \
|
||||||
arr = NULL; \
|
(arr) = NULL; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
#define array_push_value(arr, value) \
|
#define array_push_value(arr, value) \
|
||||||
do { \
|
do { \
|
||||||
|
if ((arr) == NULL) { \
|
||||||
|
array_create(arr); \
|
||||||
|
} \
|
||||||
ArrayHeader* header = array_get_header(arr); \
|
ArrayHeader* header = array_get_header(arr); \
|
||||||
if (header->size + 1 > header->capacity) { \
|
if (header->size >= header->capacity) { \
|
||||||
size_t new_capacity = header->capacity * DYNAMIC_ARRAY_CAPACITY_FACTOR; \
|
size_t new_capacity = header->capacity * DYNAMIC_ARRAY_CAPACITY_FACTOR; \
|
||||||
ArrayHeader *new_header = realloc(header, sizeof(*arr) * new_capacity + sizeof(ArrayHeader)); \
|
ArrayHeader* new_header = \
|
||||||
if (new_header != NULL) { \
|
realloc(header, sizeof(*(arr)) * new_capacity + sizeof(ArrayHeader)); \
|
||||||
|
if (new_header == NULL) { \
|
||||||
|
abort(); \
|
||||||
|
} \
|
||||||
header = new_header; \
|
header = new_header; \
|
||||||
} \
|
|
||||||
header->capacity = new_capacity; \
|
header->capacity = new_capacity; \
|
||||||
arr = (void *)(header + 1); \
|
(arr) = (void*)(header + 1); \
|
||||||
} \
|
} \
|
||||||
arr[header->size] = value; \
|
(arr)[header->size] = (value); \
|
||||||
header->size++; \
|
header->size++; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
#define array_pop(arr) \
|
#define array_pop(arr) \
|
||||||
do { \
|
do { \
|
||||||
|
if ((arr) == NULL) { \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
ArrayHeader* header = array_get_header(arr); \
|
ArrayHeader* header = array_get_header(arr); \
|
||||||
|
if (header->size == 0) { \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
header->size--; \
|
header->size--; \
|
||||||
} while (0)
|
} 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
|
#endif
|
||||||
@@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
#include "dynamic_array.h"
|
#include "dynamic_array.h"
|
||||||
|
|
||||||
|
void setUp(void) {
|
||||||
|
}
|
||||||
|
|
||||||
void setUp(void) {}
|
void tearDown(void) {
|
||||||
|
}
|
||||||
void tearDown(void) {}
|
|
||||||
|
|
||||||
|
|
||||||
void test_array_create_without_options(void) {
|
void test_array_create_without_options(void) {
|
||||||
int* arr = NULL;
|
int* arr = NULL;
|
||||||
@@ -18,7 +18,6 @@ void test_array_create_without_options(void) {
|
|||||||
array_destroy(arr);
|
array_destroy(arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void test_array_destroy(void) {
|
void test_array_destroy(void) {
|
||||||
int* arr = NULL;
|
int* arr = NULL;
|
||||||
array_create(arr);
|
array_create(arr);
|
||||||
@@ -26,7 +25,6 @@ void test_array_destroy(void) {
|
|||||||
TEST_ASSERT_NULL(arr);
|
TEST_ASSERT_NULL(arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void test_array_size_initial(void) {
|
void test_array_size_initial(void) {
|
||||||
int* arr = NULL;
|
int* arr = NULL;
|
||||||
array_create(arr);
|
array_create(arr);
|
||||||
@@ -36,7 +34,6 @@ void test_array_size_initial(void) {
|
|||||||
array_destroy(arr);
|
array_destroy(arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void test_array_push_value(void) {
|
void test_array_push_value(void) {
|
||||||
int* arr = NULL;
|
int* arr = NULL;
|
||||||
array_create(arr);
|
array_create(arr);
|
||||||
@@ -49,7 +46,6 @@ void test_array_push_value(void) {
|
|||||||
array_destroy(arr);
|
array_destroy(arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void test_array_push_multiple_values(void) {
|
void test_array_push_multiple_values(void) {
|
||||||
int* arr = NULL;
|
int* arr = NULL;
|
||||||
array_create(arr);
|
array_create(arr);
|
||||||
@@ -66,7 +62,6 @@ void test_array_push_multiple_values(void) {
|
|||||||
array_destroy(arr);
|
array_destroy(arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void test_array_pop_decrements_size(void) {
|
void test_array_pop_decrements_size(void) {
|
||||||
int* arr = NULL;
|
int* arr = NULL;
|
||||||
array_create(arr);
|
array_create(arr);
|
||||||
@@ -80,6 +75,22 @@ void test_array_pop_decrements_size(void) {
|
|||||||
array_destroy(arr);
|
array_destroy(arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_array_pop_on_empty_is_noop(void) {
|
||||||
|
int* arr = NULL;
|
||||||
|
array_create(arr);
|
||||||
|
|
||||||
|
array_push_value(arr, 99);
|
||||||
|
TEST_ASSERT_EQUAL(1, array_get_header(arr)->size);
|
||||||
|
TEST_ASSERT_EQUAL(99, arr[0]);
|
||||||
|
|
||||||
|
array_pop(arr);
|
||||||
|
TEST_ASSERT_EQUAL(0, array_get_header(arr)->size);
|
||||||
|
|
||||||
|
array_pop(arr); // should not underflow
|
||||||
|
TEST_ASSERT_EQUAL(0, array_get_header(arr)->size);
|
||||||
|
|
||||||
|
array_destroy(arr);
|
||||||
|
}
|
||||||
|
|
||||||
void test_array_get_capacity_default(void) {
|
void test_array_get_capacity_default(void) {
|
||||||
int* arr = NULL;
|
int* arr = NULL;
|
||||||
@@ -90,7 +101,6 @@ void test_array_get_capacity_default(void) {
|
|||||||
array_destroy(arr);
|
array_destroy(arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void test_array_size_capacity_relationship(void) {
|
void test_array_size_capacity_relationship(void) {
|
||||||
int* arr = NULL;
|
int* arr = NULL;
|
||||||
array_create(arr);
|
array_create(arr);
|
||||||
@@ -106,7 +116,6 @@ void test_array_size_capacity_relationship(void) {
|
|||||||
array_destroy(arr);
|
array_destroy(arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void test_array_push_beyond_capacity(void) {
|
void test_array_push_beyond_capacity(void) {
|
||||||
int* arr = NULL;
|
int* arr = NULL;
|
||||||
array_create(arr);
|
array_create(arr);
|
||||||
@@ -123,7 +132,6 @@ void test_array_push_beyond_capacity(void) {
|
|||||||
array_destroy(arr);
|
array_destroy(arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void test_array_values_correct_after_growth(void) {
|
void test_array_values_correct_after_growth(void) {
|
||||||
int* arr = NULL;
|
int* arr = NULL;
|
||||||
array_create(arr);
|
array_create(arr);
|
||||||
@@ -141,9 +149,84 @@ void test_array_values_correct_after_growth(void) {
|
|||||||
array_destroy(arr);
|
array_destroy(arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_array_looping(void) {
|
||||||
|
int* arr = NULL;
|
||||||
|
array_create(arr);
|
||||||
|
|
||||||
int main(void)
|
const int num_elements = DYNAMIC_ARRAY_DEFAULT_ARRAY_SIZE * 2;
|
||||||
{
|
for (int i = 0; i < num_elements; i++) {
|
||||||
|
array_push_value(arr, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ArrayHeader* header = array_get_header(arr);
|
||||||
|
TEST_ASSERT_EQUAL(num_elements, header->size);
|
||||||
|
|
||||||
|
for (int i = 0; i < header->size; i++) {
|
||||||
|
TEST_ASSERT_EQUAL(i, arr[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- 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();
|
UNITY_BEGIN();
|
||||||
|
|
||||||
RUN_TEST(test_array_create_without_options);
|
RUN_TEST(test_array_create_without_options);
|
||||||
@@ -152,10 +235,21 @@ int main(void)
|
|||||||
RUN_TEST(test_array_push_value);
|
RUN_TEST(test_array_push_value);
|
||||||
RUN_TEST(test_array_push_multiple_values);
|
RUN_TEST(test_array_push_multiple_values);
|
||||||
RUN_TEST(test_array_pop_decrements_size);
|
RUN_TEST(test_array_pop_decrements_size);
|
||||||
|
RUN_TEST(test_array_pop_on_empty_is_noop);
|
||||||
RUN_TEST(test_array_get_capacity_default);
|
RUN_TEST(test_array_get_capacity_default);
|
||||||
RUN_TEST(test_array_size_capacity_relationship);
|
RUN_TEST(test_array_size_capacity_relationship);
|
||||||
RUN_TEST(test_array_push_beyond_capacity);
|
RUN_TEST(test_array_push_beyond_capacity);
|
||||||
RUN_TEST(test_array_values_correct_after_growth);
|
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();
|
return UNITY_END();
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user