From 2f39963b3e4611193c7a259d33bf1bf837a7304d Mon Sep 17 00:00:00 2001 From: Bailey Thompson Date: Thu, 11 Jan 2018 21:54:49 -0500 Subject: [PATCH] Make sure containers are valid upon initialization When initializing a container, the arguments are now checked for validity. This is done by verifying that data sizes are not 0 and that function pointers are not NULL. --- src/array.c | 25 ++++++----- src/deque.c | 7 ++- src/forward_list.c | 50 +++++++++++---------- src/list.c | 66 ++++++++++++++------------- src/map.c | 10 +++-- src/multimap.c | 14 ++++-- src/multiset.c | 9 +++- src/priority_queue.c | 8 +++- src/queue.c | 7 ++- src/set.c | 8 +++- src/stack.c | 8 +++- src/unordered_map.c | 13 ++++-- src/unordered_multimap.c | 11 ++++- src/unordered_multiset.c | 10 ++++- src/unordered_set.c | 10 ++++- src/vector.c | 97 +++++++++++++++++++++------------------- 16 files changed, 214 insertions(+), 139 deletions(-) diff --git a/src/array.c b/src/array.c index 07b3095..5252eec 100644 --- a/src/array.c +++ b/src/array.c @@ -26,27 +26,30 @@ #include "array.h" struct internal_array { - size_t data_size; - int element_count; + size_t bytes_per_item; + int item_count; void *data; }; /** * Initializes an array, which is a static contiguous array. * - * @param element_count The amount of elements in the array. - * @param data_size The size of each element in the array. + * @param element_count The amount of elements in the array. Must be positive. + * @param data_size The size of each element in the array. Must be positive. * * @return The newly-initialized array, or NULL if memory allocation error. */ array array_init(const int element_count, const size_t data_size) { + if (element_count <= 0 || data_size == 0) { + return NULL; + } struct internal_array *const init = malloc(sizeof(struct internal_array)); if (!init) { return NULL; } - init->data_size = data_size; - init->element_count = element_count; + init->bytes_per_item = data_size; + init->item_count = element_count; init->data = calloc((size_t) element_count, data_size); if (!init->data) { free(init); @@ -64,7 +67,7 @@ array array_init(const int element_count, const size_t data_size) */ int array_size(array me) { - return me->element_count; + return me->item_count; } /** @@ -75,7 +78,7 @@ int array_size(array me) */ void array_copy_to_array(void *const arr, array me) { - memcpy(arr, me->data, me->element_count * me->data_size); + memcpy(arr, me->data, me->item_count * me->bytes_per_item); } /** @@ -98,7 +101,7 @@ void *array_get_data(array me) */ static bool array_is_illegal_input(array me, const int index) { - return index < 0 || index >= me->element_count; + return index < 0 || index >= me->item_count; } /** @@ -116,7 +119,7 @@ int array_set(array me, const int index, void *const data) if (array_is_illegal_input(me, index)) { return -EINVAL; } - memcpy(me->data + index * me->data_size, data, me->data_size); + memcpy(me->data + index * me->bytes_per_item, data, me->bytes_per_item); return 0; } @@ -135,7 +138,7 @@ int array_get(void *const data, array me, const int index) if (array_is_illegal_input(me, index)) { return -EINVAL; } - memcpy(data, me->data + index * me->data_size, me->data_size); + memcpy(data, me->data + index * me->bytes_per_item, me->bytes_per_item); return 0; } diff --git a/src/deque.c b/src/deque.c index c6388ce..053b302 100644 --- a/src/deque.c +++ b/src/deque.c @@ -44,12 +44,15 @@ struct node { /** * Initializes a deque, which is a doubly-ended queue. * - * @param data_size The size of each element in the deque. + * @param data_size The size of each element in the deque. Must be positive. * - * @return The newly-allocated deque, or NULL if could not allocate memory. + * @return The newly-initialized deque, or NULL if memory allocation error. */ deque deque_init(const size_t data_size) { + if (data_size == 0) { + return NULL; + } struct internal_deque *const init = malloc(sizeof(struct internal_deque)); if (!init) { return NULL; diff --git a/src/forward_list.c b/src/forward_list.c index 36c4683..88c3383 100644 --- a/src/forward_list.c +++ b/src/forward_list.c @@ -26,8 +26,8 @@ #include "forward_list.h" struct internal_forward_list { - size_t data_size; - int space; + size_t bytes_per_item; + int item_count; struct node *head; }; @@ -39,19 +39,23 @@ struct node { /** * Initializes a singly-linked list. * - * @param data_size The size of data to store. + * @param data_size The size of data to store. Must be positive. * - * @return The singly-linked list, or NULL if memory could not be allocated. + * @return The newly-initialized singly-linked list, or NULL if memory + * allocation error. */ forward_list forward_list_init(const size_t data_size) { + if (data_size == 0) { + return NULL; + } struct internal_forward_list *const init = malloc(sizeof(struct internal_forward_list)); if (!init) { return NULL; } - init->data_size = data_size; - init->space = 0; + init->bytes_per_item = data_size; + init->item_count = 0; init->head = NULL; return init; } @@ -65,7 +69,7 @@ forward_list forward_list_init(const size_t data_size) */ int forward_list_size(forward_list me) { - return me->space; + return me->item_count; } /** @@ -91,8 +95,8 @@ void forward_list_copy_to_array(void *const arr, forward_list me) struct node *traverse = me->head; int offset = 0; while (traverse) { - memcpy(arr + offset, traverse->data, me->data_size); - offset += me->data_size; + memcpy(arr + offset, traverse->data, me->bytes_per_item); + offset += me->bytes_per_item; traverse = traverse->next; } } @@ -136,19 +140,19 @@ int forward_list_add_first(forward_list me, void *const data) */ int forward_list_add_at(forward_list me, const int index, void *const data) { - if (index < 0 || index > me->space) { + if (index < 0 || index > me->item_count) { return -EINVAL; } struct node *const add = malloc(sizeof(struct node)); if (!add) { return -ENOMEM; } - add->data = malloc(me->data_size); + add->data = malloc(me->bytes_per_item); if (!add->data) { free(add); return -ENOMEM; } - memcpy(add->data, data, me->data_size); + memcpy(add->data, data, me->bytes_per_item); if (index == 0) { add->next = me->head; me->head = add; @@ -157,7 +161,7 @@ int forward_list_add_at(forward_list me, const int index, void *const data) add->next = traverse->next; traverse->next = add; } - me->space++; + me->item_count++; return 0; } @@ -172,7 +176,7 @@ int forward_list_add_at(forward_list me, const int index, void *const data) */ int forward_list_add_last(forward_list me, void *const data) { - return forward_list_add_at(me, me->space, data); + return forward_list_add_at(me, me->item_count, data); } /* @@ -180,7 +184,7 @@ int forward_list_add_last(forward_list me, void *const data) */ static bool forward_list_is_illegal_input(forward_list me, const int index) { - return index < 0 || index >= me->space || me->space == 0; + return index < 0 || index >= me->item_count || me->item_count == 0; } /** @@ -215,7 +219,7 @@ int forward_list_remove_at(forward_list me, const int index) me->head = temp->next; free(temp->data); free(temp); - } else if (index == me->space - 1) { + } else if (index == me->item_count - 1) { struct node *const traverse = forward_list_get_node_at(me, index - 1); free(traverse->next->data); free(traverse->next); @@ -227,7 +231,7 @@ int forward_list_remove_at(forward_list me, const int index) free(backup->data); free(backup); } - me->space--; + me->item_count--; return 0; } @@ -241,7 +245,7 @@ int forward_list_remove_at(forward_list me, const int index) */ int forward_list_remove_last(forward_list me) { - return forward_list_remove_at(me, me->space - 1); + return forward_list_remove_at(me, me->item_count - 1); } /** @@ -274,7 +278,7 @@ int forward_list_set_at(forward_list me, const int index, void *const data) return -EINVAL; } struct node *const traverse = forward_list_get_node_at(me, index); - memcpy(traverse->data, data, me->data_size); + memcpy(traverse->data, data, me->bytes_per_item); return 0; } @@ -289,7 +293,7 @@ int forward_list_set_at(forward_list me, const int index, void *const data) */ int forward_list_set_last(forward_list me, void *const data) { - return forward_list_set_at(me, me->space - 1, data); + return forward_list_set_at(me, me->item_count - 1, data); } /** @@ -322,7 +326,7 @@ int forward_list_get_at(void *const data, forward_list me, const int index) return -EINVAL; } struct node *const traverse = forward_list_get_node_at(me, index); - memcpy(data, traverse->data, me->data_size); + memcpy(data, traverse->data, me->bytes_per_item); return 0; } @@ -337,7 +341,7 @@ int forward_list_get_at(void *const data, forward_list me, const int index) */ int forward_list_get_last(void *const data, forward_list me) { - return forward_list_get_at(data, me, me->space - 1); + return forward_list_get_at(data, me, me->item_count - 1); } /** @@ -355,7 +359,7 @@ void forward_list_clear(forward_list me) free(temp); } me->head = NULL; - me->space = 0; + me->item_count = 0; } /** diff --git a/src/list.c b/src/list.c index 9cc4f68..acc6fd0 100644 --- a/src/list.c +++ b/src/list.c @@ -26,8 +26,8 @@ #include "list.h" struct internal_list { - size_t data_size; - int space; + size_t bytes_per_item; + int item_count; struct node *head; struct node *tail; }; @@ -41,18 +41,22 @@ struct node { /** * Initializes a doubly-linked list. * - * @param data_size The size of data to store. + * @param data_size The size of data to store. Must be positive. * - * @return The doubly-linked list, or NULL if memory could not be allocated. + * @return The newly-initialized doubly-linked list, or NULL if memory + * allocation error. */ list list_init(const size_t data_size) { + if (data_size == 0) { + return NULL; + } struct internal_list *const init = malloc(sizeof(struct internal_list)); if (!init) { return NULL; } - init->data_size = data_size; - init->space = 0; + init->bytes_per_item = data_size; + init->item_count = 0; init->head = NULL; init->tail = NULL; return init; @@ -67,7 +71,7 @@ list list_init(const size_t data_size) */ int list_size(list me) { - return me->space; + return me->item_count; } /** @@ -93,8 +97,8 @@ void list_copy_to_array(void *const arr, list me) struct node *traverse = me->head; int offset = 0; while (traverse) { - memcpy(arr + offset, traverse->data, me->data_size); - offset += me->data_size; + memcpy(arr + offset, traverse->data, me->bytes_per_item); + offset += me->bytes_per_item; traverse = traverse->next; } } @@ -117,7 +121,7 @@ static struct node *list_get_node_from_head(list me, const int index) static struct node *list_get_node_from_tail(list me, const int index) { struct node *traverse = me->tail; - for (int i = me->space - 1; i > index; i--) { + for (int i = me->item_count - 1; i > index; i--) { traverse = traverse->prev; } return traverse; @@ -128,7 +132,7 @@ static struct node *list_get_node_from_tail(list me, const int index) */ static struct node *list_get_node_at(list me, const int index) { - if (index <= me->space / 2) { + if (index <= me->item_count / 2) { return list_get_node_from_head(me, index); } else { return list_get_node_from_tail(me, index); @@ -151,13 +155,13 @@ int list_add_first(list me, void *const data) if (!add) { return -ENOMEM; } - add->data = malloc(me->data_size); + add->data = malloc(me->bytes_per_item); if (!add->data) { free(add); return -ENOMEM; } add->prev = NULL; - memcpy(add->data, data, me->data_size); + memcpy(add->data, data, me->bytes_per_item); add->next = traverse; if (traverse) { traverse->prev = add; @@ -166,7 +170,7 @@ int list_add_first(list me, void *const data) if (!me->tail) { me->tail = traverse; } - me->space++; + me->item_count++; return 0; } @@ -183,13 +187,13 @@ int list_add_first(list me, void *const data) */ int list_add_at(list me, const int index, void *const data) { - if (index < 0 || index > me->space) { + if (index < 0 || index > me->item_count) { return -EINVAL; } if (index == 0) { return list_add_first(me, data); } - if (index == me->space) { + if (index == me->item_count) { return list_add_last(me, data); } // The new node will go right before this node. @@ -198,17 +202,17 @@ int list_add_at(list me, const int index, void *const data) if (!add) { return -ENOMEM; } - add->data = malloc(me->data_size); + add->data = malloc(me->bytes_per_item); if (!add->data) { free(add); return -ENOMEM; } add->prev = traverse->prev; - memcpy(add->data, data, me->data_size); + memcpy(add->data, data, me->bytes_per_item); add->next = traverse; traverse->prev->next = add; traverse->prev = add; - me->space++; + me->item_count++; return 0; } @@ -228,19 +232,19 @@ int list_add_last(list me, void *const data) if (!add) { return -ENOMEM; } - add->data = malloc(me->data_size); + add->data = malloc(me->bytes_per_item); if (!add->data) { free(add); return -ENOMEM; } add->prev = traverse; - memcpy(add->data, data, me->data_size); + memcpy(add->data, data, me->bytes_per_item); add->next = NULL; if (traverse) { traverse->next = add; } me->tail = add; - me->space++; + me->item_count++; return 0; } @@ -249,7 +253,7 @@ int list_add_last(list me, void *const data) */ static bool list_is_illegal_input(list me, const int index) { - return index < 0 || index >= me->space || me->space == 0; + return index < 0 || index >= me->item_count || me->item_count == 0; } /** @@ -283,7 +287,7 @@ int list_remove_at(list me, const int index) if (index == 0) { traverse->next->prev = NULL; me->head = traverse->next; - } else if (index == me->space - 1) { + } else if (index == me->item_count - 1) { traverse->prev->next = NULL; me->tail = traverse->prev; } else { @@ -292,7 +296,7 @@ int list_remove_at(list me, const int index) } free(traverse->data); free(traverse); - me->space--; + me->item_count--; return 0; } @@ -306,7 +310,7 @@ int list_remove_at(list me, const int index) */ int list_remove_last(list me) { - return list_remove_at(me, me->space - 1); + return list_remove_at(me, me->item_count - 1); } /** @@ -339,7 +343,7 @@ int list_set_at(list me, const int index, void *const data) return -EINVAL; } struct node *const traverse = list_get_node_at(me, index); - memcpy(traverse->data, data, me->data_size); + memcpy(traverse->data, data, me->bytes_per_item); return 0; } @@ -354,7 +358,7 @@ int list_set_at(list me, const int index, void *const data) */ int list_set_last(list me, void *const data) { - return list_set_at(me, me->space - 1, data); + return list_set_at(me, me->item_count - 1, data); } /** @@ -387,7 +391,7 @@ int list_get_at(void *const data, list me, const int index) return -EINVAL; } struct node *const traverse = list_get_node_at(me, index); - memcpy(data, traverse->data, me->data_size); + memcpy(data, traverse->data, me->bytes_per_item); return 0; } @@ -402,7 +406,7 @@ int list_get_at(void *const data, list me, const int index) */ int list_get_last(void *const data, list me) { - return list_get_at(data, me, me->space - 1); + return list_get_at(data, me, me->item_count - 1); } /** @@ -420,7 +424,7 @@ void list_clear(list me) free(temp); } me->head = NULL; - me->space = 0; + me->item_count = 0; me->tail = NULL; } diff --git a/src/map.c b/src/map.c index db7c37e..3f90410 100644 --- a/src/map.c +++ b/src/map.c @@ -46,9 +46,10 @@ struct node { * Initializes a map, which is a collection of key-value pairs, sorted by keys, * keys are unique * - * @param key_size The size of each key in the map. - * @param value_size The size of each value in the map. - * @param comparator The comparator function used for key ordering. + * @param key_size The size of each key in the map. Must be positive. + * @param value_size The size of each value in the map. Must be positive. + * @param comparator The comparator function used for key ordering. Must not be + * NULL. * * @return The newly-initialized map, or NULL if memory allocation error. */ @@ -56,6 +57,9 @@ map map_init(const size_t key_size, const size_t value_size, int (*const comparator)(const void *const, const void *const)) { + if (key_size == 0 || value_size == 0 || !comparator) { + return NULL; + } struct internal_map *const init = malloc(sizeof(struct internal_map)); if (!init) { return NULL; diff --git a/src/multimap.c b/src/multimap.c index efcb694..883eb04 100644 --- a/src/multimap.c +++ b/src/multimap.c @@ -54,10 +54,12 @@ struct value_node { * Initializes a multi-map, which is a collection of key-value pairs, sorted by * keys. * - * @param key_size The size of each key in the multi-map. - * @param value_size The size of each value in the multi-map. - * @param key_comparator The key comparator function. - * @param value_comparator The value comparator function. + * @param key_size The size of each key in the multi-map. Must be + * positive. + * @param value_size The size of each value in the multi-map. Must be + * positive. + * @param key_comparator The key comparator function. Must not be NULL. + * @param value_comparator The value comparator function. Must not be NULL. * * @return The newly-initialized multi-map, or NULL if memory allocation error. */ @@ -68,6 +70,10 @@ multimap multimap_init(const size_t key_size, int (*const value_comparator)(const void *const, const void *const)) { + if (key_size == 0 || value_size == 0 + || !key_comparator || !value_comparator) { + return NULL; + } struct internal_multimap *const init = malloc(sizeof(struct internal_multimap)); if (!init) { diff --git a/src/multiset.c b/src/multiset.c index 6bbe5ae..2fc62b1 100644 --- a/src/multiset.c +++ b/src/multiset.c @@ -45,8 +45,10 @@ struct node { * Initializes a multi-set, which is a collection of key-value pairs, sorted by * keys, keys are unique * - * @param key_size The size of each element in the multi-set. - * @param comparator The comparator function used for key ordering. + * @param key_size The size of each element in the multi-set. Must be + * positive. + * @param comparator The comparator function used for key ordering. Must not be + * NULL. * * @return The newly-initialized multi-set, or NULL if memory allocation error. */ @@ -54,6 +56,9 @@ multiset multiset_init(const size_t key_size, int (*const comparator)(const void *const, const void *const)) { + if (key_size == 0 || !comparator) { + return NULL; + } struct internal_multiset *const init = malloc(sizeof(struct internal_multiset)); if (!init) { diff --git a/src/priority_queue.c b/src/priority_queue.c index 8080c54..a0575af 100644 --- a/src/priority_queue.c +++ b/src/priority_queue.c @@ -36,8 +36,9 @@ struct internal_priority_queue { * Initializes a priority queue, which adapts a container to provide priority * queue. Adapts the vector container. * - * @param data_size The size of the data in the priority queue. - * @param comparator The priority comparator function. + * @param data_size The size of the data in the priority queue. Must be + * positive. + * @param comparator The priority comparator function. Must not be NULL. * * @return The newly-initialized priority queue, or NULL if memory allocation * error. @@ -46,6 +47,9 @@ priority_queue priority_queue_init(const size_t data_size, int (*comparator)(const void *const, const void *const)) { + if (data_size == 0 || !comparator) { + return NULL; + } struct internal_priority_queue *const init = malloc(sizeof(struct internal_priority_queue)); if (!init) { diff --git a/src/queue.c b/src/queue.c index f945c63..ec18dab 100644 --- a/src/queue.c +++ b/src/queue.c @@ -35,12 +35,15 @@ struct internal_queue { * Initializes a queue, which adapts a container to provide queue * (first-in first-out). Adapts the deque container. * - * @param data_size The size of each element. + * @param data_size The size of each element. Must be positive. * - * @return The newly-initialized queue, or NULL if out of memory. + * @return The newly-initialized queue, or NULL if memory allocation error. */ queue queue_init(const size_t data_size) { + if (data_size == 0) { + return NULL; + } struct internal_queue *const init = malloc(sizeof(struct internal_queue)); if (!init) { return NULL; diff --git a/src/set.c b/src/set.c index b94cc83..b7916b3 100644 --- a/src/set.c +++ b/src/set.c @@ -43,14 +43,18 @@ struct node { /** * Initializes a set, which is a collection of unique keys, sorted by keys. * - * @param key_size The size of each element in the set. - * @param comparator The comparator function used for key ordering. + * @param key_size The size of each element in the set. Must be positive. + * @param comparator The comparator function used for key ordering. Must not be + * NULL. * * @return The newly-initialized set, or NULL if memory allocation error. */ set set_init(const size_t key_size, int (*const comparator)(const void *const, const void *const)) { + if (key_size == 0 || !comparator) { + return NULL; + } struct internal_set *const init = malloc(sizeof(struct internal_set)); if (!init) { return NULL; diff --git a/src/stack.c b/src/stack.c index 9c2443e..5782c68 100644 --- a/src/stack.c +++ b/src/stack.c @@ -32,12 +32,16 @@ struct internal_stack { * Initializes a stack, which adapts a container to provide stack * (last-in first-out). Adapts the deque container. * - * @param data_size The size of each data element in the stack. + * @param data_size The size of each data element in the stack. Must be + * positive. * - * @return The newly-initialized stack, or NULL if could not allocate memory. + * @return The newly-initialized stack, or NULL if memory allocation error. */ stack stack_init(const size_t data_size) { + if (data_size == 0) { + return NULL; + } struct internal_stack *const init = malloc(sizeof(struct internal_stack)); if (!init) { return NULL; diff --git a/src/unordered_map.c b/src/unordered_map.c index 04e31f2..fae4b28 100644 --- a/src/unordered_map.c +++ b/src/unordered_map.c @@ -50,10 +50,14 @@ struct node { * Initializes an unordered map, which is a collection of key-value pairs, * hashed by keys, keys are unique * - * @param key_size The size of each key in the unordered map. - * @param value_size The size of each value in the unordered map. + * @param key_size The size of each key in the unordered map. Must be + * positive. + * @param value_size The size of each value in the unordered map. Must be + * positive. * @param hash The hash function which computes the hash from the key. - * @param comparator The comparator function which compares two keys. + * Must not be NULL. + * @param comparator The comparator function which compares two keys. Must not + * be NULL. * * @return The newly-initialized unordered map, or NULL if memory allocation * error. @@ -64,6 +68,9 @@ unordered_map unordered_map_init(const size_t key_size, int (*comparator)(const void *const, const void *const)) { + if (key_size == 0 || value_size == 0 || !hash || !comparator) { + return NULL; + } struct internal_unordered_map *const init = malloc(sizeof(struct internal_unordered_map)); if (!init) { diff --git a/src/unordered_multimap.c b/src/unordered_multimap.c index 03de28b..02f74ed 100644 --- a/src/unordered_multimap.c +++ b/src/unordered_multimap.c @@ -54,11 +54,16 @@ struct node { * Initializes an unordered multi-map, which is a collection of key-value pairs, * hashed by keys * - * @param key_size The size of each key in the unordered multi-map. + * @param key_size The size of each key in the unordered multi-map. Must + * be positive. * @param value_size The size of each value in the unordered multi-map. + * Must be positive. * @param hash The hash function which computes the hash from key. + * Must not be NULL. * @param key_comparator The comparator function which compares two keys. + * Must not be NULL. * @param value_comparator The comparator function which compares two values. + * Must not be NULL. * * @return The newly-initialized unordered multi-map, or NULL if memory * allocation error. @@ -72,6 +77,10 @@ unordered_multimap_init(const size_t key_size, int (*value_comparator)(const void *const, const void *const)) { + if (key_size == 0 || value_size == 0 + || !hash || !key_comparator || !value_comparator) { + return NULL; + } struct internal_unordered_multimap *const init = malloc(sizeof(struct internal_unordered_multimap)); if (!init) { diff --git a/src/unordered_multiset.c b/src/unordered_multiset.c index e0a092e..9c617a0 100644 --- a/src/unordered_multiset.c +++ b/src/unordered_multiset.c @@ -50,9 +50,12 @@ struct node { * Initializes an unordered multi-set, which is a collection of keys, hashed by * keys. * - * @param key_size The size of each key in the unordered multi-set. + * @param key_size The size of each key in the unordered multi-set. Must be + * positive. * @param hash The hash function which computes the hash from the key. - * @param comparator The comparator function which compares two keys. + * Must not be NULL. + * @param comparator The comparator function which compares two keys. Must not + * be NULL. * * @return The newly-initialized unordered multi-set, or NULL if memory * allocation error. @@ -62,6 +65,9 @@ unordered_multiset_init(const size_t key_size, unsigned long (*hash)(const void *const), int (*comparator)(const void *const, const void *const)) { + if (key_size == 0 || !hash || !comparator) { + return NULL; + } struct internal_unordered_multiset *const init = malloc(sizeof(struct internal_unordered_multiset)); if (!init) { diff --git a/src/unordered_set.c b/src/unordered_set.c index fa27e90..24010a1 100644 --- a/src/unordered_set.c +++ b/src/unordered_set.c @@ -48,9 +48,12 @@ struct node { * Initializes an unordered set, which is a collection of unique keys, hashed by * keys. * - * @param key_size The size of each key in the unordered set. + * @param key_size The size of each key in the unordered set. Must be + * positive. * @param hash The hash function which computes the hash from the key. - * @param comparator The comparator function which compares two keys. + * Must not be NULL. + * @param comparator The comparator function which compares two keys. Must not + * be NULL. * * @return The newly-initialized unordered set, or NULL if memory allocation * error. @@ -60,6 +63,9 @@ unordered_set unordered_set_init(const size_t key_size, int (*comparator)(const void *const, const void *const)) { + if (key_size == 0 || !hash || !comparator) { + return NULL; + } struct internal_unordered_set *const init = malloc(sizeof(struct internal_unordered_set)); if (!init) { diff --git a/src/vector.c b/src/vector.c index f8c758b..61fa5f3 100644 --- a/src/vector.c +++ b/src/vector.c @@ -29,30 +29,33 @@ static const int START_SPACE = 8; static const double RESIZE_RATIO = 1.5; struct internal_vector { - size_t data_size; - int offset; - int space; - void *storage; + size_t bytes_per_item; + int item_count; + int item_capacity; + void *data; }; /** * Initializes a vector, which is a dynamic contiguous array. * - * @param data_size The size of each element in the vector. + * @param data_size The size of each element in the vector. Must be positive. * * @return The newly-initialized vector, or NULL if memory allocation error. */ vector vector_init(const size_t data_size) { + if (data_size == 0) { + return NULL; + } struct internal_vector *const init = malloc(sizeof(struct internal_vector)); if (!init) { return NULL; } - init->data_size = data_size; - init->offset = 0; - init->space = START_SPACE; - init->storage = malloc(init->space * init->data_size); - if (!init->storage) { + init->bytes_per_item = data_size; + init->item_count = 0; + init->item_capacity = START_SPACE; + init->data = malloc(init->item_capacity * init->bytes_per_item); + if (!init->data) { free(init); return NULL; } @@ -68,7 +71,7 @@ vector vector_init(const size_t data_size) */ int vector_size(vector me) { - return me->offset; + return me->item_count; } /** @@ -88,14 +91,14 @@ bool vector_is_empty(vector me) */ static int vector_set_space(vector me, const int size) { - void *const temp = realloc(me->storage, size * me->data_size); + void *const temp = realloc(me->data, size * me->bytes_per_item); if (!temp) { return -ENOMEM; } - me->storage = temp; - me->space = size; - if (me->space < me->offset) { - me->offset = me->space; + me->data = temp; + me->item_capacity = size; + if (me->item_capacity < me->item_count) { + me->item_count = me->item_capacity; } return 0; } @@ -112,7 +115,7 @@ static int vector_set_space(vector me, const int size) */ int vector_reserve(vector me, int size) { - if (me->space >= size) { + if (me->item_capacity >= size) { return 0; } return vector_set_space(me, size); @@ -128,7 +131,7 @@ int vector_reserve(vector me, int size) */ int vector_trim(vector me) { - return vector_set_space(me, me->offset); + return vector_set_space(me, me->item_count); } /** @@ -139,7 +142,7 @@ int vector_trim(vector me) */ void vector_copy_to_array(void *const arr, vector me) { - memcpy(arr, me->storage, me->offset * me->data_size); + memcpy(arr, me->data, me->item_count * me->bytes_per_item); } /** @@ -154,7 +157,7 @@ void vector_copy_to_array(void *const arr, vector me) */ void *vector_get_data(vector me) { - return me->storage; + return me->data; } /** @@ -184,25 +187,25 @@ int vector_add_first(vector me, void *const data) */ int vector_add_at(vector me, const int index, void *const data) { - if (index < 0 || index > me->offset) { + if (index < 0 || index > me->item_count) { return -EINVAL; } - if (me->offset + 1 >= me->space) { - const int new_space = (int) (me->space * RESIZE_RATIO); - void *const temp = realloc(me->storage, new_space * me->data_size); + if (me->item_count + 1 >= me->item_capacity) { + const int new_space = (int) (me->item_capacity * RESIZE_RATIO); + void *const temp = realloc(me->data, new_space * me->bytes_per_item); if (!temp) { return -ENOMEM; } - me->storage = temp; - me->space = new_space; + me->data = temp; + me->item_capacity = new_space; } - if (index != me->offset) { - memmove(me->storage + (index + 1) * me->data_size, - me->storage + index * me->data_size, - (me->offset - index) * me->data_size); + if (index != me->item_count) { + memmove(me->data + (index + 1) * me->bytes_per_item, + me->data + index * me->bytes_per_item, + (me->item_count - index) * me->bytes_per_item); } - memcpy(me->storage + index * me->data_size, data, me->data_size); - me->offset++; + memcpy(me->data + index * me->bytes_per_item, data, me->bytes_per_item); + me->item_count++; return 0; } @@ -217,7 +220,7 @@ int vector_add_at(vector me, const int index, void *const data) */ int vector_add_last(vector me, void *const data) { - return vector_add_at(me, me->offset, data); + return vector_add_at(me, me->item_count, data); } /* @@ -225,7 +228,7 @@ int vector_add_last(vector me, void *const data) */ static bool vector_is_illegal_input(vector me, const int index) { - return index < 0 || index >= me->offset || me->offset == 0; + return index < 0 || index >= me->item_count || me->item_count == 0; } /** @@ -255,10 +258,10 @@ int vector_remove_at(vector me, const int index) if (vector_is_illegal_input(me, index)) { return -EINVAL; } - me->offset--; - memmove(me->storage + index * me->data_size, - me->storage + (index + 1) * me->data_size, - (me->offset - index) * me->data_size); + me->item_count--; + memmove(me->data + index * me->bytes_per_item, + me->data + (index + 1) * me->bytes_per_item, + (me->item_count - index) * me->bytes_per_item); return 0; } @@ -272,10 +275,10 @@ int vector_remove_at(vector me, const int index) */ int vector_remove_last(vector me) { - if (me->offset == 0) { + if (me->item_count == 0) { return -EINVAL; } - me->offset--; + me->item_count--; return 0; } @@ -307,7 +310,7 @@ int vector_set_at(vector me, const int index, void *const data) if (vector_is_illegal_input(me, index)) { return -EINVAL; } - memcpy(me->storage + index * me->data_size, data, me->data_size); + memcpy(me->data + index * me->bytes_per_item, data, me->bytes_per_item); return 0; } @@ -321,7 +324,7 @@ int vector_set_at(vector me, const int index, void *const data) */ int vector_set_last(vector me, void *const data) { - return vector_set_at(me, me->offset - 1, data); + return vector_set_at(me, me->item_count - 1, data); } /** @@ -353,7 +356,7 @@ int vector_get_at(void *const data, vector me, const int index) if (vector_is_illegal_input(me, index)) { return -EINVAL; } - memcpy(data, me->storage + index * me->data_size, me->data_size); + memcpy(data, me->data + index * me->bytes_per_item, me->bytes_per_item); return 0; } @@ -368,7 +371,7 @@ int vector_get_at(void *const data, vector me, const int index) */ int vector_get_last(void *const data, vector me) { - return vector_get_at(data, me, me->offset - 1); + return vector_get_at(data, me, me->item_count - 1); } /** @@ -382,7 +385,7 @@ int vector_get_last(void *const data, vector me) int vector_clear(vector me) { const int ret = vector_set_space(me, START_SPACE); - me->offset = 0; + me->item_count = 0; return ret; } @@ -395,8 +398,8 @@ int vector_clear(vector me) */ vector vector_destroy(vector me) { - free(me->storage); - me->storage = NULL; + free(me->data); + me->data = NULL; free(me); return NULL; }