diff --git a/include/arraylist.h b/include/arraylist.h index 93df972..60cc16d 100644 --- a/include/arraylist.h +++ b/include/arraylist.h @@ -24,7 +24,7 @@ typedef enum { ArrayList *arraylist_init(size_t capacity, size_t elem_size); ArrayListErr arraylist_destroy(ArrayList **arr); ArrayListErr arraylist_clear(ArrayList *arr); -ArrayList *arraylist_copy(ArrayList *arr); +ArrayList *arraylist_copy(const ArrayList *arr); size_t arraylist_size(const ArrayList *arr); size_t arraylist_capacity(const ArrayList *arr); @@ -50,19 +50,19 @@ 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(ArraySlice *slice); -size_t arrayslice_size(ArraySlice *slice); -bool arrayslice_empty(ArraySlice *slice); +bool arrayslice_is_valid(const ArraySlice *slice); +size_t arrayslice_size(const ArraySlice *slice); +bool arrayslice_empty(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(ArraySlice *slice, void *out); +ArrayListErr *arrayslice_peek(const ArraySlice *slice, void *out); ArrayListErr *arrayslice_next(ArraySlice *slice, void *out); -ArrayListErr *arrayslice_get(ArraySlice *slice, void *out); +ArrayListErr *arrayslice_get(const ArraySlice *slice, void *out); ArrayListErr *arrayslice_reset(ArraySlice *slice); ArrayListErr *arrayslice_advance(ArraySlice *slice, size_t n); -ArrayList *arrayslice_to_arraylist(ArraySlice *slice); +ArrayList *arrayslice_to_arraylist(const ArraySlice *slice); #endif diff --git a/src/arraylist.c b/src/arraylist.c index 01d0001..e517f7b 100644 --- a/src/arraylist.c +++ b/src/arraylist.c @@ -60,6 +60,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); @@ -73,6 +77,10 @@ ArrayListErr arraylist_clear(ArrayList *arr) { return ARRLIST_NULL_ARG; } + if (arr->borrows > 0) { + return ARRLIST_IS_BORROWED; + } + arr->len = 0; return ARRLIST_OK; } @@ -140,6 +148,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); @@ -158,6 +170,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); @@ -188,6 +204,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; } @@ -218,6 +238,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; } @@ -246,6 +270,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; } @@ -280,6 +308,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; } @@ -345,6 +377,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; } @@ -368,6 +404,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) { @@ -386,3 +426,78 @@ 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; + } + + free(*slice); + *slice = NULL; + + return ARRLIST_OK; +}