diff --git a/include/arraylist.h b/include/arraylist.h index 3fbf677..a22f97e 100644 --- a/include/arraylist.h +++ b/include/arraylist.h @@ -7,15 +7,7 @@ typedef struct ArrayList ArrayList; -// FUCK, i forgot one of the main reasons i wanted to -// implement arrays myself was because i needed -// array slices or something like this and i completely -// forgot, fuck, guess i will implement it once i get -// the tests done. -typedef struct { - ArrayList *array; - size_t offset; -} ArrayListSlice; +typedef struct ArraySlice ArraySlice; typedef enum { ARRLIST_OK = 0, @@ -26,11 +18,14 @@ typedef enum { ARRLIST_NULL_ARG, ARRLIST_INVALID_ELEM_SIZE, ARRLIST_INVALID_CAPACITY, + ARRLIST_IS_BORROWED, + ARRLIST_INVALID_SLICE, } ArrayListErr; ArrayList *arraylist_init(size_t capacity, size_t elem_size); ArrayListErr arraylist_destroy(ArrayList **arr); ArrayListErr arraylist_clear(ArrayList *arr); +ArrayList *arraylist_clone(const ArrayList *arr); size_t arraylist_size(const ArrayList *arr); size_t arraylist_capacity(const ArrayList *arr); @@ -51,4 +46,22 @@ ArrayListErr arraylist_set(ArrayList *arr, size_t index, void *data); ArrayListErr arraylist_resize(ArrayList *arr, size_t new_capacity); ArrayListErr arraylist_reserve(ArrayList *arr, size_t size_to_reserve); +//Slice stuff +ArraySlice *arraylist_slice(ArrayList *arr, size_t start, size_t len); +ArraySlice *arraylist_slice_unsafe(ArrayList *arr, size_t start, size_t len); +ArrayListErr arrayslice_destroy(ArraySlice **slice); + +bool arrayslice_is_valid(const ArraySlice *slice); +size_t arrayslice_size(const ArraySlice *slice); + +// peek and next can be null, get can't, like, why would you use get without +// actually getting something?, for validating an index?, use size idiot +ArrayListErr arrayslice_peek(const ArraySlice *slice, void *out); +ArrayListErr arrayslice_next(ArraySlice *slice, void *out); + +ArrayListErr arrayslice_reset(ArraySlice *slice); +ArrayListErr arrayslice_advance(ArraySlice *slice, size_t n); + +ArrayList *arrayslice_to_arraylist(const ArraySlice *slice); + #endif diff --git a/src/arraylist.c b/src/arraylist.c index f29e7b0..bbbaa65 100644 --- a/src/arraylist.c +++ b/src/arraylist.c @@ -9,6 +9,15 @@ struct ArrayList{ size_t capacity; size_t len; size_t elem_size; + size_t borrows; +}; + +struct ArraySlice { + ArrayList *arr; + size_t start; + size_t end; + size_t current; + bool is_safe; }; // Grow and shrink factor is 2, 1.5 might give different results i guess @@ -37,6 +46,7 @@ ArrayList *arraylist_init(size_t capacity, size_t elem_size) { arr->capacity = capacity; arr->elem_size = elem_size; arr->len = 0; + arr->borrows = 0; arr->buffer = malloc(capacity * elem_size); if (arr->buffer == NULL) { free(arr); @@ -51,6 +61,10 @@ ArrayListErr arraylist_destroy(ArrayList **arr) { return ARRLIST_NULL_ARG; } + if ((*arr)->borrows > 0) { + return ARRLIST_IS_BORROWED; + } + // No problem on using free on NULL :) free((*arr)->buffer); free(*arr); @@ -64,6 +78,10 @@ ArrayListErr arraylist_clear(ArrayList *arr) { return ARRLIST_NULL_ARG; } + if (arr->borrows > 0) { + return ARRLIST_IS_BORROWED; + } + arr->len = 0; return ARRLIST_OK; } @@ -131,6 +149,10 @@ ArrayListErr arraylist_push_back(ArrayList *arr, void *data) { return ARRLIST_NULL_ARG; } + if (arr->borrows > 0) { + return ARRLIST_IS_BORROWED; + } + if (arr->len >= arr->capacity) { ArrayListErr err = arraylist_grow(arr); @@ -149,6 +171,10 @@ ArrayListErr arraylist_push_front(ArrayList *arr, void *data) { return ARRLIST_NULL_ARG; } + if (arr->borrows > 0) { + return ARRLIST_IS_BORROWED; + } + if (arr->len >= arr->capacity) { ArrayListErr err = arraylist_grow(arr); @@ -179,6 +205,10 @@ ArrayListErr arraylist_insert(ArrayList *arr, size_t index, void *data) { return ARRLIST_NULL_ARG; } + if (arr->borrows > 0) { + return ARRLIST_IS_BORROWED; + } + if (index > arr->len) { return ARRLIST_OUT_OF_BOUNDS; } @@ -209,6 +239,10 @@ ArrayListErr arraylist_pop_back(ArrayList *arr, void *out) { return ARRLIST_NULL_ARG; } + if (arr->borrows > 0) { + return ARRLIST_IS_BORROWED; + } + if (arr->len < 1) { return ARRLIST_EMPTY; } @@ -237,6 +271,10 @@ ArrayListErr arraylist_pop_front(ArrayList *arr, void *out) { return ARRLIST_NULL_ARG; } + if (arr->borrows > 0) { + return ARRLIST_IS_BORROWED; + } + if (arr->len < 1) { return ARRLIST_EMPTY; } @@ -271,6 +309,10 @@ ArrayListErr arraylist_remove_at(ArrayList *arr, size_t index, void *out) { return ARRLIST_NULL_ARG; } + if (arr->borrows > 0) { + return ARRLIST_IS_BORROWED; + } + if (index >= arr->len) { return ARRLIST_OUT_OF_BOUNDS; } @@ -336,6 +378,10 @@ ArrayListErr arraylist_resize(ArrayList *arr, size_t new_capacity) { return ARRLIST_NULL_ARG; } + if (arr->borrows > 0) { + return ARRLIST_IS_BORROWED; + } + if (new_capacity < 1) { return ARRLIST_INVALID_CAPACITY; } @@ -359,6 +405,10 @@ ArrayListErr arraylist_reserve(ArrayList *arr, size_t size_to_reserve) { return ARRLIST_NULL_ARG; } + if (arr->borrows > 0) { + return ARRLIST_IS_BORROWED; + } + if (arr->capacity + size_to_reserve > SIZE_MAX / arr->elem_size || size_to_reserve > SIZE_MAX / arr->elem_size) { @@ -377,3 +427,180 @@ ArrayListErr arraylist_reserve(ArrayList *arr, size_t size_to_reserve) { arr->capacity += size_to_reserve; return ARRLIST_OK; } + +ArraySlice *arraylist_slice(ArrayList *arr, size_t start, size_t len) { + if (arr == NULL) { + return NULL; + } + + if (arr->len == 0 || len == 0) { + return NULL; + } + + if (start > SIZE_MAX / arr->elem_size || len > SIZE_MAX / arr->elem_size) { + return NULL; + } + + if (start + len > arr->len) { + return NULL; + } + + ArraySlice *slice = malloc(sizeof(ArraySlice)); + if (slice == NULL) { + return NULL; + } + + slice->arr = arr; + slice->start = start; + slice->end = start + len; + slice->current = start; + slice->is_safe = true; + + arr->borrows++; + + return slice; +} + +ArraySlice *arraylist_slice_unsafe(ArrayList *arr, size_t start, size_t len) { + if (arr == NULL) { + return NULL; + } + + if (arr->len == 0 || len == 0) { + return NULL; + } + + if (start > SIZE_MAX / arr->elem_size || len > SIZE_MAX / arr->elem_size) { + return NULL; + } + + if (start + len > arr->len) { + return NULL; + } + + ArraySlice *slice = malloc(sizeof(ArraySlice)); + if (slice == NULL) { + return NULL; + } + + slice->arr = arr; + slice->start = start; + slice->end = start + len; + slice->current = start; + slice->is_safe = false; + + return slice; +} + +ArrayListErr arrayslice_destroy(ArraySlice **slice) { + if (slice == NULL || *slice == NULL) { + return ARRLIST_NULL_ARG; + } + + if ((*slice)->is_safe) { + (*slice)->arr->borrows--; + } + + free(*slice); + *slice = NULL; + + return ARRLIST_OK; +} + +bool arrayslice_is_valid(const ArraySlice *slice) { + if (slice == NULL) { + return false; + } + + return slice->current != slice->end; +} + +size_t arrayslice_size(const ArraySlice *slice) { + if (slice == NULL) { + return 0; + } + + return slice->end - slice->start; +} + +ArrayListErr arrayslice_peek(const ArraySlice *slice, void *out) { + if (slice == NULL || out == NULL) { + return ARRLIST_NULL_ARG; + } + + if (slice->current >= slice->end) { + return ARRLIST_INVALID_SLICE; + } + + arraylist_get(slice->arr, slice->current, out); + + return ARRLIST_OK; +} + +ArrayListErr arrayslice_next(ArraySlice *slice, void *out) { + // HERE, it makes sense that you want to advance to the next + // without actually getting the value so it's good + if (slice == NULL) { + return ARRLIST_NULL_ARG; + } + + if (slice->current == slice->end) { + return ARRLIST_INVALID_SLICE; + } + + arraylist_get(slice->arr, slice->current, out); + + slice->current++; + return ARRLIST_OK; +} + +ArrayListErr arrayslice_reset(ArraySlice *slice) { + if (slice == NULL) { + return ARRLIST_NULL_ARG; + } + + slice->current = slice->start; + + return ARRLIST_OK; +} + +ArrayListErr arrayslice_advance(ArraySlice *slice, size_t n) { + if (slice == NULL) { + return ARRLIST_NULL_ARG; + } + + if (n > SIZE_MAX - slice->current || slice->current + n > slice->end) { + return ARRLIST_OUT_OF_BOUNDS; + } + + slice->current += n; + + return ARRLIST_OK; +} + +ArrayList *arrayslice_to_arraylist(const ArraySlice *slice) { + if (slice == NULL || slice->arr == NULL) { + return NULL; + } + + if (slice->start >= slice->end) { + return NULL; + } + + size_t len = slice->end - slice->start; + + ArrayList *new_arr = arraylist_init(arraylist_capacity(slice->arr), slice->arr->elem_size); + if (new_arr == NULL) { + return NULL; + } + + memcpy( + new_arr->buffer, + slice->arr->buffer + (slice->start * slice->arr->elem_size), + slice->arr->elem_size * len + ); + + new_arr->len = len; + + return new_arr; +} diff --git a/test/test_arraylist.c b/test/test_arraylist.c index 42942fb..1362d41 100644 --- a/test/test_arraylist.c +++ b/test/test_arraylist.c @@ -80,6 +80,26 @@ static void test_destroy_double(void **state) { assert_null(arr); } +static void test_destroy_while_borrowed(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + + assert_uint_equal(arraylist_destroy(&arr), ARRLIST_IS_BORROWED); + + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + // State static void test_capacity_after_init(void **state) { (void) state; @@ -254,6 +274,26 @@ static void test_push_back_null_data(void **state) { arraylist_destroy(&arr); } +static void test_push_back_while_borrowed(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + int n = 8; + assert_uint_equal(arraylist_push_back(arr, &n), ARRLIST_IS_BORROWED); + + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + // Push front static void test_push_front_single_element(void **state) { (void) state; @@ -311,6 +351,26 @@ static void test_push_front_null_data(void **state) { arraylist_destroy(&arr); } +static void test_push_front_while_borrowed(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + int n = 8; + assert_uint_equal(arraylist_push_front(arr, &n), ARRLIST_IS_BORROWED); + + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + // Insert static void test_insert_at_beginning(void **state) { (void) state; @@ -409,6 +469,26 @@ static void test_insert_null_data(void **state) { arraylist_destroy(&arr); } +static void test_insert_while_borrowed(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + int n = 8; + assert_uint_equal(arraylist_insert(arr, 2, &n), ARRLIST_IS_BORROWED); + + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + // Pop back static void test_pop_back_single_element(void **state) { (void) state; @@ -504,6 +584,26 @@ static void test_pop_back_null_out(void **state) { arraylist_destroy(&arr); } +static void test_pop_back_while_borrowed(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + int n = 8; + assert_uint_equal(arraylist_pop_back(arr, &n), ARRLIST_IS_BORROWED); + + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + // Pop front static void test_pop_front_single_element(void **state) { (void) state; @@ -601,6 +701,26 @@ static void test_pop_front_null_out(void **state) { arraylist_destroy(&arr); } +static void test_pop_front_while_borrowed(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + int n = 8; + assert_uint_equal(arraylist_pop_front(arr, &n), ARRLIST_IS_BORROWED); + + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + // Remove at static void test_remove_at_beginning(void **state) { (void) state; @@ -695,6 +815,26 @@ static void test_remove_at_null_data(void **state) { arraylist_destroy(&arr); } +static void test_remove_at_while_borrowed(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + int n = 8; + assert_uint_equal(arraylist_remove_at(arr, 5, &n), ARRLIST_IS_BORROWED); + + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + // Get static void test_get_valid_index(void **state) { (void) state; @@ -788,6 +928,26 @@ static void test_get_null_out(void **state) { arraylist_destroy(&arr); } +static void test_get_while_borrowed(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + int n = 8; + assert_uint_equal(arraylist_get(arr, 5, &n), ARRLIST_OK); + + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + // Set static void test_set_valid_index(void **state) { (void) state; @@ -883,6 +1043,26 @@ static void test_set_null_data(void **state) { arraylist_destroy(&arr); } +static void test_set_while_borrowed(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + int n = 8; + assert_uint_equal(arraylist_set(arr, 5, &n), ARRLIST_OK); + + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + //Clear static void test_clear_non_empty_array(void **state) { (void) state; @@ -920,6 +1100,25 @@ static void test_clear_null_array(void **state) { assert_uint_equal(arraylist_clear(arr), ARRLIST_NULL_ARG); } +static void test_clear_while_borrowed(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + assert_uint_equal(arraylist_clear(arr), ARRLIST_IS_BORROWED); + + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + //Resize static void test_resize_increase_capacity(void **state) { (void) state; @@ -977,6 +1176,25 @@ static void test_resize_null_array(void **state) { assert_uint_equal(arraylist_resize(arr, 65), ARRLIST_NULL_ARG); } +static void test_resize_while_borrowed(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + assert_uint_equal(arraylist_resize(arr, 128), ARRLIST_IS_BORROWED); + + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + // Reserve static void test_reserve_normal_capacity(void **state) { (void) state; @@ -1014,6 +1232,582 @@ static void test_reserve_size_0(void **state) { arraylist_destroy(&arr); } +static void test_reserve_while_borrowed(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + assert_uint_equal(arraylist_reserve(arr, 128), ARRLIST_IS_BORROWED); + + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + +// Slice creation +static void test_slice_valid_init(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (size_t i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, 10); + assert_non_null(slice); + + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + +static void test_slice_invalid_index(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (size_t i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 32, 10); + assert_null(slice); + + arraylist_destroy(&arr); +} + +static void test_slice_invalid_len(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (size_t i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, 300); + assert_null(slice); + + arraylist_destroy(&arr); +} + +static void test_slice_len_zero(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (size_t i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, 0); + assert_null(slice); + + arraylist_destroy(&arr); +} + +static void test_slice_empty_array(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + + ArraySlice *slice = arraylist_slice(arr, 0, 10); + assert_null(slice); + + arraylist_destroy(&arr); +} + +static void test_slice_null_arr(void **state) { + (void) state; + + ArrayList *arr = NULL; + + ArraySlice *slice = arraylist_slice(arr, 0, 10); + assert_null(slice); +} + +// Slice Unsafe +static void test_slice_unsafe_valid_init(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (size_t i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, 10); + assert_non_null(slice); + + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + +static void test_slice_unsafe_invalid_index(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (size_t i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 32, 10); + assert_null(slice); + + arraylist_destroy(&arr); +} + +static void test_slice_unsafe_invalid_len(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (size_t i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, 300); + assert_null(slice); + + arraylist_destroy(&arr); +} + +static void test_slice_unsafe_len_zero(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (size_t i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, 0); + assert_null(slice); + + arraylist_destroy(&arr); +} + +static void test_slice_unsafe_empty_array(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + + ArraySlice *slice = arraylist_slice(arr, 0, 10); + assert_null(slice); + + arraylist_destroy(&arr); +} + +static void test_slice_unsafe_null_arr(void **state) { + (void) state; + + ArrayList *arr = NULL; + + ArraySlice *slice = arraylist_slice(arr, 0, 10); + assert_null(slice); +} + +// Slice Destroy +static void test_slice_destroy_valid(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + assert_uint_equal(arrayslice_destroy(&slice), ARRLIST_OK); + arraylist_destroy(&arr); +} + +static void test_slice_destroy_null_slice(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = NULL; + + assert_uint_equal(arrayslice_destroy(&slice), ARRLIST_NULL_ARG); + arraylist_destroy(&arr); +} + +static void test_slice_double_destroy(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + assert_uint_equal(arrayslice_destroy(&slice), ARRLIST_OK); + assert_uint_equal(arrayslice_destroy(&slice), ARRLIST_NULL_ARG); + arraylist_destroy(&arr); +} + +// Slice peek +static void test_slice_peek_valid_array(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + int m; + assert_uint_equal(arrayslice_peek(slice, &m), ARRLIST_OK); + assert_int_equal(m, 0); + + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + +static void test_slice_peek_invalid_array(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + assert_uint_equal(arrayslice_advance(slice, 10), ARRLIST_OK); + + int m; + assert_uint_equal(arrayslice_peek(slice, &m), ARRLIST_INVALID_SLICE); + assert_int_equal(m, 0); + + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + +static void test_slice_peek_null_out(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + assert_uint_equal(arrayslice_peek(slice, NULL), ARRLIST_NULL_ARG); + + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + +static void test_slice_peek_null_slice(void **state) { + (void) state; + + ArraySlice *slice = NULL; + + int m; + assert_uint_equal(arrayslice_peek(slice, &m), ARRLIST_NULL_ARG); + assert_int_equal(m, 0); +} + +// Slice next +static void test_slice_next_valid_array(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + int m; + assert_uint_equal(arrayslice_next(slice, &m), ARRLIST_OK); + assert_int_equal(m, 0); + + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + +static void test_slice_next_invalid_array(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + assert_uint_equal(arrayslice_advance(slice, 10), ARRLIST_OK); + + int m; + assert_uint_equal(arrayslice_next(slice, &m), ARRLIST_INVALID_SLICE); + assert_int_equal(m, 0); + + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + +static void test_slice_next_null_out(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + assert_uint_equal(arrayslice_next(slice, NULL), ARRLIST_OK); + + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + +static void test_slice_next_null_slice(void **state) { + (void) state; + + ArraySlice *slice = NULL; + + int m; + assert_uint_equal(arrayslice_next(slice, &m), ARRLIST_NULL_ARG); + assert_int_equal(m, 0); +} + +static void test_slice_next_until_invalid(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + int m; + for (int i = 0; i < 10; i++) { + assert_uint_equal(arrayslice_next(slice, &m), ARRLIST_OK); + assert_uint_equal(m, i); + } + assert_false(arrayslice_is_valid(slice)); + + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + +//Slice reset +static void test_slice_reset_valid_slice(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + int m; + for (int i = 0; i < 10; i++) { + assert_uint_equal(arrayslice_next(slice, &m), ARRLIST_OK); + assert_uint_equal(m, i); + } + + assert_uint_equal(arrayslice_reset(slice), ARRLIST_OK); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arrayslice_next(slice, &m), ARRLIST_OK); + assert_uint_equal(m, i); + } + + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + +static void test_slice_reset_null_slice(void **state) { + (void) state; + + ArraySlice *slice = NULL; + + assert_uint_equal(arrayslice_reset(slice), ARRLIST_NULL_ARG); +} + +//Slice advance +//out ou bounds +//null +static void test_slice_advance_valid_slice(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + int m; + for (int i = 0; i < 5; i++) { + assert_uint_equal(arrayslice_next(slice, &m), ARRLIST_OK); + assert_uint_equal(m, i); + } + + assert_uint_equal(arrayslice_advance(slice, 5), ARRLIST_OK); + + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + +static void test_slice_advance_out_of_bounds(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + int m; + for (int i = 0; i < 5; i++) { + assert_uint_equal(arrayslice_next(slice, &m), ARRLIST_OK); + assert_uint_equal(m, i); + } + + assert_uint_equal(arrayslice_advance(slice, 40), ARRLIST_OUT_OF_BOUNDS); + + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + +static void test_slice_advance_size_max(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + int m; + for (int i = 0; i < 5; i++) { + assert_uint_equal(arrayslice_next(slice, &m), ARRLIST_OK); + assert_uint_equal(m, i); + } + + assert_uint_equal(arrayslice_advance(slice, SIZE_MAX), ARRLIST_OUT_OF_BOUNDS); + + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + +static void test_slice_advance_null_array(void **state) { + (void) state; + + ArraySlice *slice = NULL; + + assert_uint_equal(arrayslice_advance(slice, 56), ARRLIST_NULL_ARG); +} + +//Slice to Array +static void test_slice_to_array_valid(void **state) { + (void) state; + + ArrayList *arr = arraylist_init(64, sizeof(int)); + assert_non_null(arr); + + for (int i = 0; i < 10; i++) { + assert_uint_equal(arraylist_push_back(arr, &i), ARRLIST_OK); + } + + ArraySlice *slice = arraylist_slice(arr, 0, arraylist_size(arr)); + assert_non_null(slice); + + ArrayList *arr2 = arrayslice_to_arraylist(slice); + assert_non_null(arr2); + assert_uint_equal(arraylist_capacity(arr2), 64); + assert_uint_equal(arraylist_size(arr2), 10); + + arraylist_destroy(&arr2); + arrayslice_destroy(&slice); + arraylist_destroy(&arr); +} + +static void test_slice_to_array_null_slice(void **state) { + (void) state; + + ArraySlice *slice = NULL; + + assert_null(arrayslice_to_arraylist(slice)); +} + int main(void) { const struct CMUnitTest init[] = { cmocka_unit_test(test_init_valid_parameters), @@ -1026,6 +1820,7 @@ int main(void) { cmocka_unit_test(test_destroy_valid_array), cmocka_unit_test(test_destroy_null_array), cmocka_unit_test(test_destroy_double), + cmocka_unit_test(test_destroy_while_borrowed), }; const struct CMUnitTest state[] = { @@ -1042,6 +1837,7 @@ int main(void) { cmocka_unit_test(test_push_back_multiple_elements), cmocka_unit_test(test_push_back_null_array), cmocka_unit_test(test_push_back_null_data), + cmocka_unit_test(test_push_back_while_borrowed), }; const struct CMUnitTest push_front[] = { @@ -1049,6 +1845,7 @@ int main(void) { cmocka_unit_test(test_push_front_multiple_elements), cmocka_unit_test(test_push_front_null_array), cmocka_unit_test(test_push_front_null_data), + cmocka_unit_test(test_push_front_while_borrowed), }; const struct CMUnitTest insert[] = { @@ -1058,6 +1855,7 @@ int main(void) { cmocka_unit_test(test_insert_at_invalid_index), cmocka_unit_test(test_insert_null_array), cmocka_unit_test(test_insert_null_data), + cmocka_unit_test(test_insert_while_borrowed), }; const struct CMUnitTest pop_back[] = { @@ -1067,6 +1865,7 @@ int main(void) { cmocka_unit_test(test_pop_back_empty_array), cmocka_unit_test(test_pop_back_null_array), cmocka_unit_test(test_pop_back_null_out), + cmocka_unit_test(test_pop_back_while_borrowed), }; const struct CMUnitTest pop_front[] = { @@ -1076,6 +1875,7 @@ int main(void) { cmocka_unit_test(test_pop_front_empty_array), cmocka_unit_test(test_pop_front_null_array), cmocka_unit_test(test_pop_front_null_out), + cmocka_unit_test(test_pop_front_while_borrowed), }; const struct CMUnitTest remove_at[] = { @@ -1085,6 +1885,7 @@ int main(void) { cmocka_unit_test(test_remove_at_invalid_index), cmocka_unit_test(test_remove_at_null_array), cmocka_unit_test(test_remove_at_null_data), + cmocka_unit_test(test_remove_at_while_borrowed), }; const struct CMUnitTest get[] = { @@ -1094,6 +1895,7 @@ int main(void) { cmocka_unit_test(test_get_invalid_index), cmocka_unit_test(test_get_null_array), cmocka_unit_test(test_get_null_out), + cmocka_unit_test(test_get_while_borrowed), }; const struct CMUnitTest set[] = { @@ -1103,12 +1905,14 @@ int main(void) { cmocka_unit_test(test_set_invalid_index), cmocka_unit_test(test_set_null_array), cmocka_unit_test(test_set_null_data), + cmocka_unit_test(test_set_while_borrowed), }; const struct CMUnitTest clear[] = { cmocka_unit_test(test_clear_non_empty_array), cmocka_unit_test(test_clear_already_empty_array), cmocka_unit_test(test_clear_null_array), + cmocka_unit_test(test_clear_while_borrowed), }; const struct CMUnitTest resize[] = { @@ -1117,12 +1921,70 @@ int main(void) { cmocka_unit_test(test_resize_to_zero), cmocka_unit_test(test_resize_to_size_max), cmocka_unit_test(test_resize_null_array), + cmocka_unit_test(test_resize_while_borrowed), }; const struct CMUnitTest reserve[] = { cmocka_unit_test(test_reserve_normal_capacity), cmocka_unit_test(test_reserve_size_0), cmocka_unit_test(test_reserve_size_max), + cmocka_unit_test(test_reserve_while_borrowed), + }; + + const struct CMUnitTest slice_array[] = { + cmocka_unit_test(test_slice_valid_init), + cmocka_unit_test(test_slice_invalid_index), + cmocka_unit_test(test_slice_invalid_len), + cmocka_unit_test(test_slice_len_zero), + cmocka_unit_test(test_slice_empty_array), + cmocka_unit_test(test_slice_null_arr), + }; + + const struct CMUnitTest slice_array_unsafe[] = { + cmocka_unit_test(test_slice_unsafe_valid_init), + cmocka_unit_test(test_slice_unsafe_invalid_index), + cmocka_unit_test(test_slice_unsafe_invalid_len), + cmocka_unit_test(test_slice_unsafe_len_zero), + cmocka_unit_test(test_slice_unsafe_empty_array), + cmocka_unit_test(test_slice_unsafe_null_arr), + }; + + const struct CMUnitTest slice_destroy[] = { + cmocka_unit_test(test_slice_destroy_valid), + cmocka_unit_test(test_slice_destroy_null_slice), + cmocka_unit_test(test_slice_double_destroy), + }; + + const struct CMUnitTest slice_peek[] = { + cmocka_unit_test(test_slice_peek_valid_array), + cmocka_unit_test(test_slice_peek_invalid_array), + cmocka_unit_test(test_slice_peek_null_slice), + cmocka_unit_test(test_slice_peek_null_out), + }; + + const struct CMUnitTest slice_next[] = { + cmocka_unit_test(test_slice_next_valid_array), + cmocka_unit_test(test_slice_next_invalid_array), + cmocka_unit_test(test_slice_next_null_slice), + cmocka_unit_test(test_slice_next_null_out), + cmocka_unit_test(test_slice_next_until_invalid), + }; + + const struct CMUnitTest slice_reset[] = { + cmocka_unit_test(test_slice_reset_valid_slice), + cmocka_unit_test(test_slice_reset_null_slice), + }; + + const struct CMUnitTest slice_advance[] = { + cmocka_unit_test(test_slice_advance_valid_slice), + cmocka_unit_test(test_slice_advance_out_of_bounds), + cmocka_unit_test(test_slice_advance_null_array), + cmocka_unit_test(test_slice_advance_size_max), + }; + + const struct CMUnitTest slice_to_array[] = { + cmocka_unit_test(test_slice_to_array_valid), + cmocka_unit_test(test_slice_to_array_null_slice), }; int rc = 0; @@ -1142,5 +2004,14 @@ int main(void) { rc += cmocka_run_group_tests(resize, NULL, NULL); rc += cmocka_run_group_tests(reserve, NULL, NULL); + rc += cmocka_run_group_tests(slice_array, NULL, NULL); + rc += cmocka_run_group_tests(slice_array_unsafe, NULL, NULL); + rc += cmocka_run_group_tests(slice_destroy, NULL, NULL); + rc += cmocka_run_group_tests(slice_peek, NULL, NULL); + rc += cmocka_run_group_tests(slice_next, NULL, NULL); + rc += cmocka_run_group_tests(slice_reset, NULL, NULL); + rc += cmocka_run_group_tests(slice_advance, NULL, NULL); + rc += cmocka_run_group_tests(slice_to_array, NULL, NULL); + return rc; }