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.
This commit is contained in:
Bailey Thompson
2018-01-11 21:54:49 -05:00
committed by GitHub
parent c51bdfefef
commit 2f39963b3e
16 changed files with 214 additions and 139 deletions

View File

@@ -26,27 +26,30 @@
#include "array.h" #include "array.h"
struct internal_array { struct internal_array {
size_t data_size; size_t bytes_per_item;
int element_count; int item_count;
void *data; void *data;
}; };
/** /**
* Initializes an array, which is a static contiguous array. * Initializes an array, which is a static contiguous array.
* *
* @param element_count The amount of elements 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. * @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. * @return The newly-initialized array, or NULL if memory allocation error.
*/ */
array array_init(const int element_count, const size_t data_size) 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)); struct internal_array *const init = malloc(sizeof(struct internal_array));
if (!init) { if (!init) {
return NULL; return NULL;
} }
init->data_size = data_size; init->bytes_per_item = data_size;
init->element_count = element_count; init->item_count = element_count;
init->data = calloc((size_t) element_count, data_size); init->data = calloc((size_t) element_count, data_size);
if (!init->data) { if (!init->data) {
free(init); free(init);
@@ -64,7 +67,7 @@ array array_init(const int element_count, const size_t data_size)
*/ */
int array_size(array me) 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) 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) 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)) { if (array_is_illegal_input(me, index)) {
return -EINVAL; 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; return 0;
} }
@@ -135,7 +138,7 @@ int array_get(void *const data, array me, const int index)
if (array_is_illegal_input(me, index)) { if (array_is_illegal_input(me, index)) {
return -EINVAL; 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; return 0;
} }

View File

@@ -44,12 +44,15 @@ struct node {
/** /**
* Initializes a deque, which is a doubly-ended queue. * 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) deque deque_init(const size_t data_size)
{ {
if (data_size == 0) {
return NULL;
}
struct internal_deque *const init = malloc(sizeof(struct internal_deque)); struct internal_deque *const init = malloc(sizeof(struct internal_deque));
if (!init) { if (!init) {
return NULL; return NULL;

View File

@@ -26,8 +26,8 @@
#include "forward_list.h" #include "forward_list.h"
struct internal_forward_list { struct internal_forward_list {
size_t data_size; size_t bytes_per_item;
int space; int item_count;
struct node *head; struct node *head;
}; };
@@ -39,19 +39,23 @@ struct node {
/** /**
* Initializes a singly-linked list. * 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) forward_list forward_list_init(const size_t data_size)
{ {
if (data_size == 0) {
return NULL;
}
struct internal_forward_list *const init = struct internal_forward_list *const init =
malloc(sizeof(struct internal_forward_list)); malloc(sizeof(struct internal_forward_list));
if (!init) { if (!init) {
return NULL; return NULL;
} }
init->data_size = data_size; init->bytes_per_item = data_size;
init->space = 0; init->item_count = 0;
init->head = NULL; init->head = NULL;
return init; return init;
} }
@@ -65,7 +69,7 @@ forward_list forward_list_init(const size_t data_size)
*/ */
int forward_list_size(forward_list me) 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; struct node *traverse = me->head;
int offset = 0; int offset = 0;
while (traverse) { while (traverse) {
memcpy(arr + offset, traverse->data, me->data_size); memcpy(arr + offset, traverse->data, me->bytes_per_item);
offset += me->data_size; offset += me->bytes_per_item;
traverse = traverse->next; 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) 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; return -EINVAL;
} }
struct node *const add = malloc(sizeof(struct node)); struct node *const add = malloc(sizeof(struct node));
if (!add) { if (!add) {
return -ENOMEM; return -ENOMEM;
} }
add->data = malloc(me->data_size); add->data = malloc(me->bytes_per_item);
if (!add->data) { if (!add->data) {
free(add); free(add);
return -ENOMEM; return -ENOMEM;
} }
memcpy(add->data, data, me->data_size); memcpy(add->data, data, me->bytes_per_item);
if (index == 0) { if (index == 0) {
add->next = me->head; add->next = me->head;
me->head = add; 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; add->next = traverse->next;
traverse->next = add; traverse->next = add;
} }
me->space++; me->item_count++;
return 0; 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) 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) 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; me->head = temp->next;
free(temp->data); free(temp->data);
free(temp); 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); struct node *const traverse = forward_list_get_node_at(me, index - 1);
free(traverse->next->data); free(traverse->next->data);
free(traverse->next); free(traverse->next);
@@ -227,7 +231,7 @@ int forward_list_remove_at(forward_list me, const int index)
free(backup->data); free(backup->data);
free(backup); free(backup);
} }
me->space--; me->item_count--;
return 0; 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) 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; return -EINVAL;
} }
struct node *const traverse = forward_list_get_node_at(me, index); 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; 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) 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; return -EINVAL;
} }
struct node *const traverse = forward_list_get_node_at(me, index); 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; 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) 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); free(temp);
} }
me->head = NULL; me->head = NULL;
me->space = 0; me->item_count = 0;
} }
/** /**

View File

@@ -26,8 +26,8 @@
#include "list.h" #include "list.h"
struct internal_list { struct internal_list {
size_t data_size; size_t bytes_per_item;
int space; int item_count;
struct node *head; struct node *head;
struct node *tail; struct node *tail;
}; };
@@ -41,18 +41,22 @@ struct node {
/** /**
* Initializes a doubly-linked list. * 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) list list_init(const size_t data_size)
{ {
if (data_size == 0) {
return NULL;
}
struct internal_list *const init = malloc(sizeof(struct internal_list)); struct internal_list *const init = malloc(sizeof(struct internal_list));
if (!init) { if (!init) {
return NULL; return NULL;
} }
init->data_size = data_size; init->bytes_per_item = data_size;
init->space = 0; init->item_count = 0;
init->head = NULL; init->head = NULL;
init->tail = NULL; init->tail = NULL;
return init; return init;
@@ -67,7 +71,7 @@ list list_init(const size_t data_size)
*/ */
int list_size(list me) 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; struct node *traverse = me->head;
int offset = 0; int offset = 0;
while (traverse) { while (traverse) {
memcpy(arr + offset, traverse->data, me->data_size); memcpy(arr + offset, traverse->data, me->bytes_per_item);
offset += me->data_size; offset += me->bytes_per_item;
traverse = traverse->next; 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) static struct node *list_get_node_from_tail(list me, const int index)
{ {
struct node *traverse = me->tail; 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; traverse = traverse->prev;
} }
return traverse; 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) 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); return list_get_node_from_head(me, index);
} else { } else {
return list_get_node_from_tail(me, index); return list_get_node_from_tail(me, index);
@@ -151,13 +155,13 @@ int list_add_first(list me, void *const data)
if (!add) { if (!add) {
return -ENOMEM; return -ENOMEM;
} }
add->data = malloc(me->data_size); add->data = malloc(me->bytes_per_item);
if (!add->data) { if (!add->data) {
free(add); free(add);
return -ENOMEM; return -ENOMEM;
} }
add->prev = NULL; add->prev = NULL;
memcpy(add->data, data, me->data_size); memcpy(add->data, data, me->bytes_per_item);
add->next = traverse; add->next = traverse;
if (traverse) { if (traverse) {
traverse->prev = add; traverse->prev = add;
@@ -166,7 +170,7 @@ int list_add_first(list me, void *const data)
if (!me->tail) { if (!me->tail) {
me->tail = traverse; me->tail = traverse;
} }
me->space++; me->item_count++;
return 0; 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) 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; return -EINVAL;
} }
if (index == 0) { if (index == 0) {
return list_add_first(me, data); return list_add_first(me, data);
} }
if (index == me->space) { if (index == me->item_count) {
return list_add_last(me, data); return list_add_last(me, data);
} }
// The new node will go right before this node. // 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) { if (!add) {
return -ENOMEM; return -ENOMEM;
} }
add->data = malloc(me->data_size); add->data = malloc(me->bytes_per_item);
if (!add->data) { if (!add->data) {
free(add); free(add);
return -ENOMEM; return -ENOMEM;
} }
add->prev = traverse->prev; add->prev = traverse->prev;
memcpy(add->data, data, me->data_size); memcpy(add->data, data, me->bytes_per_item);
add->next = traverse; add->next = traverse;
traverse->prev->next = add; traverse->prev->next = add;
traverse->prev = add; traverse->prev = add;
me->space++; me->item_count++;
return 0; return 0;
} }
@@ -228,19 +232,19 @@ int list_add_last(list me, void *const data)
if (!add) { if (!add) {
return -ENOMEM; return -ENOMEM;
} }
add->data = malloc(me->data_size); add->data = malloc(me->bytes_per_item);
if (!add->data) { if (!add->data) {
free(add); free(add);
return -ENOMEM; return -ENOMEM;
} }
add->prev = traverse; add->prev = traverse;
memcpy(add->data, data, me->data_size); memcpy(add->data, data, me->bytes_per_item);
add->next = NULL; add->next = NULL;
if (traverse) { if (traverse) {
traverse->next = add; traverse->next = add;
} }
me->tail = add; me->tail = add;
me->space++; me->item_count++;
return 0; 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) 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) { if (index == 0) {
traverse->next->prev = NULL; traverse->next->prev = NULL;
me->head = traverse->next; me->head = traverse->next;
} else if (index == me->space - 1) { } else if (index == me->item_count - 1) {
traverse->prev->next = NULL; traverse->prev->next = NULL;
me->tail = traverse->prev; me->tail = traverse->prev;
} else { } else {
@@ -292,7 +296,7 @@ int list_remove_at(list me, const int index)
} }
free(traverse->data); free(traverse->data);
free(traverse); free(traverse);
me->space--; me->item_count--;
return 0; return 0;
} }
@@ -306,7 +310,7 @@ int list_remove_at(list me, const int index)
*/ */
int list_remove_last(list me) 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; return -EINVAL;
} }
struct node *const traverse = list_get_node_at(me, index); 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; 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) 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; return -EINVAL;
} }
struct node *const traverse = list_get_node_at(me, index); 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; 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) 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); free(temp);
} }
me->head = NULL; me->head = NULL;
me->space = 0; me->item_count = 0;
me->tail = NULL; me->tail = NULL;
} }

View File

@@ -46,9 +46,10 @@ struct node {
* Initializes a map, which is a collection of key-value pairs, sorted by keys, * Initializes a map, which is a collection of key-value pairs, sorted by keys,
* keys are unique * keys are unique
* *
* @param key_size The size of each key in the map. * @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. * @param value_size The size of each value in the map. Must be positive.
* @param comparator The comparator function used for key ordering. * @param comparator The comparator function used for key ordering. Must not be
* NULL.
* *
* @return The newly-initialized map, or NULL if memory allocation error. * @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, const size_t value_size,
int (*const comparator)(const void *const, const void *const)) 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)); struct internal_map *const init = malloc(sizeof(struct internal_map));
if (!init) { if (!init) {
return NULL; return NULL;

View File

@@ -54,10 +54,12 @@ struct value_node {
* Initializes a multi-map, which is a collection of key-value pairs, sorted by * Initializes a multi-map, which is a collection of key-value pairs, sorted by
* keys. * keys.
* *
* @param key_size The size of each key in the multi-map. * @param key_size The size of each key in the multi-map. Must be
* @param value_size The size of each value in the multi-map. * positive.
* @param key_comparator The key comparator function. * @param value_size The size of each value in the multi-map. Must be
* @param value_comparator The value comparator function. * 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. * @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, int (*const value_comparator)(const void *const,
const void *const)) const void *const))
{ {
if (key_size == 0 || value_size == 0
|| !key_comparator || !value_comparator) {
return NULL;
}
struct internal_multimap *const init = struct internal_multimap *const init =
malloc(sizeof(struct internal_multimap)); malloc(sizeof(struct internal_multimap));
if (!init) { if (!init) {

View File

@@ -45,8 +45,10 @@ struct node {
* Initializes a multi-set, which is a collection of key-value pairs, sorted by * Initializes a multi-set, which is a collection of key-value pairs, sorted by
* keys, keys are unique * keys, keys are unique
* *
* @param key_size The size of each element in the multi-set. * @param key_size The size of each element in the multi-set. Must be
* @param comparator The comparator function used for key ordering. * 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. * @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, int (*const comparator)(const void *const,
const void *const)) const void *const))
{ {
if (key_size == 0 || !comparator) {
return NULL;
}
struct internal_multiset *const init = struct internal_multiset *const init =
malloc(sizeof(struct internal_multiset)); malloc(sizeof(struct internal_multiset));
if (!init) { if (!init) {

View File

@@ -36,8 +36,9 @@ struct internal_priority_queue {
* Initializes a priority queue, which adapts a container to provide priority * Initializes a priority queue, which adapts a container to provide priority
* queue. Adapts the vector container. * queue. Adapts the vector container.
* *
* @param data_size The size of the data in the priority queue. * @param data_size The size of the data in the priority queue. Must be
* @param comparator The priority comparator function. * positive.
* @param comparator The priority comparator function. Must not be NULL.
* *
* @return The newly-initialized priority queue, or NULL if memory allocation * @return The newly-initialized priority queue, or NULL if memory allocation
* error. * error.
@@ -46,6 +47,9 @@ priority_queue priority_queue_init(const size_t data_size,
int (*comparator)(const void *const, int (*comparator)(const void *const,
const void *const)) const void *const))
{ {
if (data_size == 0 || !comparator) {
return NULL;
}
struct internal_priority_queue *const init = struct internal_priority_queue *const init =
malloc(sizeof(struct internal_priority_queue)); malloc(sizeof(struct internal_priority_queue));
if (!init) { if (!init) {

View File

@@ -35,12 +35,15 @@ struct internal_queue {
* Initializes a queue, which adapts a container to provide queue * Initializes a queue, which adapts a container to provide queue
* (first-in first-out). Adapts the deque container. * (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) queue queue_init(const size_t data_size)
{ {
if (data_size == 0) {
return NULL;
}
struct internal_queue *const init = malloc(sizeof(struct internal_queue)); struct internal_queue *const init = malloc(sizeof(struct internal_queue));
if (!init) { if (!init) {
return NULL; return NULL;

View File

@@ -43,14 +43,18 @@ struct node {
/** /**
* Initializes a set, which is a collection of unique keys, sorted by keys. * 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 key_size The size of each element in the set. Must be positive.
* @param comparator The comparator function used for key ordering. * @param comparator The comparator function used for key ordering. Must not be
* NULL.
* *
* @return The newly-initialized set, or NULL if memory allocation error. * @return The newly-initialized set, or NULL if memory allocation error.
*/ */
set set_init(const size_t key_size, set set_init(const size_t key_size,
int (*const comparator)(const void *const, const void *const)) 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)); struct internal_set *const init = malloc(sizeof(struct internal_set));
if (!init) { if (!init) {
return NULL; return NULL;

View File

@@ -32,12 +32,16 @@ struct internal_stack {
* Initializes a stack, which adapts a container to provide stack * Initializes a stack, which adapts a container to provide stack
* (last-in first-out). Adapts the deque container. * (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) stack stack_init(const size_t data_size)
{ {
if (data_size == 0) {
return NULL;
}
struct internal_stack *const init = malloc(sizeof(struct internal_stack)); struct internal_stack *const init = malloc(sizeof(struct internal_stack));
if (!init) { if (!init) {
return NULL; return NULL;

View File

@@ -50,10 +50,14 @@ struct node {
* Initializes an unordered map, which is a collection of key-value pairs, * Initializes an unordered map, which is a collection of key-value pairs,
* hashed by keys, keys are unique * hashed by keys, keys are unique
* *
* @param key_size The size of each key in the unordered map. * @param key_size The size of each key in the unordered map. Must be
* @param value_size The size of each value in the unordered map. * 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 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 * @return The newly-initialized unordered map, or NULL if memory allocation
* error. * error.
@@ -64,6 +68,9 @@ unordered_map unordered_map_init(const size_t key_size,
int (*comparator)(const void *const, int (*comparator)(const void *const,
const void *const)) const void *const))
{ {
if (key_size == 0 || value_size == 0 || !hash || !comparator) {
return NULL;
}
struct internal_unordered_map *const init = struct internal_unordered_map *const init =
malloc(sizeof(struct internal_unordered_map)); malloc(sizeof(struct internal_unordered_map));
if (!init) { if (!init) {

View File

@@ -54,11 +54,16 @@ struct node {
* Initializes an unordered multi-map, which is a collection of key-value pairs, * Initializes an unordered multi-map, which is a collection of key-value pairs,
* hashed by keys * 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. * @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. * @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. * @param key_comparator The comparator function which compares two keys.
* Must not be NULL.
* @param value_comparator The comparator function which compares two values. * @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 * @return The newly-initialized unordered multi-map, or NULL if memory
* allocation error. * allocation error.
@@ -72,6 +77,10 @@ unordered_multimap_init(const size_t key_size,
int (*value_comparator)(const void *const, int (*value_comparator)(const void *const,
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 = struct internal_unordered_multimap *const init =
malloc(sizeof(struct internal_unordered_multimap)); malloc(sizeof(struct internal_unordered_multimap));
if (!init) { if (!init) {

View File

@@ -50,9 +50,12 @@ struct node {
* Initializes an unordered multi-set, which is a collection of keys, hashed by * Initializes an unordered multi-set, which is a collection of keys, hashed by
* keys. * 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 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 * @return The newly-initialized unordered multi-set, or NULL if memory
* allocation error. * allocation error.
@@ -62,6 +65,9 @@ unordered_multiset_init(const size_t key_size,
unsigned long (*hash)(const void *const), unsigned long (*hash)(const void *const),
int (*comparator)(const void *const, 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 = struct internal_unordered_multiset *const init =
malloc(sizeof(struct internal_unordered_multiset)); malloc(sizeof(struct internal_unordered_multiset));
if (!init) { if (!init) {

View File

@@ -48,9 +48,12 @@ struct node {
* Initializes an unordered set, which is a collection of unique keys, hashed by * Initializes an unordered set, which is a collection of unique keys, hashed by
* keys. * 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 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 * @return The newly-initialized unordered set, or NULL if memory allocation
* error. * error.
@@ -60,6 +63,9 @@ unordered_set unordered_set_init(const size_t key_size,
int (*comparator)(const void *const, int (*comparator)(const void *const,
const void *const)) const void *const))
{ {
if (key_size == 0 || !hash || !comparator) {
return NULL;
}
struct internal_unordered_set *const init = struct internal_unordered_set *const init =
malloc(sizeof(struct internal_unordered_set)); malloc(sizeof(struct internal_unordered_set));
if (!init) { if (!init) {

View File

@@ -29,30 +29,33 @@ static const int START_SPACE = 8;
static const double RESIZE_RATIO = 1.5; static const double RESIZE_RATIO = 1.5;
struct internal_vector { struct internal_vector {
size_t data_size; size_t bytes_per_item;
int offset; int item_count;
int space; int item_capacity;
void *storage; void *data;
}; };
/** /**
* Initializes a vector, which is a dynamic contiguous array. * 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. * @return The newly-initialized vector, or NULL if memory allocation error.
*/ */
vector vector_init(const size_t data_size) vector vector_init(const size_t data_size)
{ {
if (data_size == 0) {
return NULL;
}
struct internal_vector *const init = malloc(sizeof(struct internal_vector)); struct internal_vector *const init = malloc(sizeof(struct internal_vector));
if (!init) { if (!init) {
return NULL; return NULL;
} }
init->data_size = data_size; init->bytes_per_item = data_size;
init->offset = 0; init->item_count = 0;
init->space = START_SPACE; init->item_capacity = START_SPACE;
init->storage = malloc(init->space * init->data_size); init->data = malloc(init->item_capacity * init->bytes_per_item);
if (!init->storage) { if (!init->data) {
free(init); free(init);
return NULL; return NULL;
} }
@@ -68,7 +71,7 @@ vector vector_init(const size_t data_size)
*/ */
int vector_size(vector me) 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) 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) { if (!temp) {
return -ENOMEM; return -ENOMEM;
} }
me->storage = temp; me->data = temp;
me->space = size; me->item_capacity = size;
if (me->space < me->offset) { if (me->item_capacity < me->item_count) {
me->offset = me->space; me->item_count = me->item_capacity;
} }
return 0; return 0;
} }
@@ -112,7 +115,7 @@ static int vector_set_space(vector me, const int size)
*/ */
int vector_reserve(vector me, int size) int vector_reserve(vector me, int size)
{ {
if (me->space >= size) { if (me->item_capacity >= size) {
return 0; return 0;
} }
return vector_set_space(me, size); return vector_set_space(me, size);
@@ -128,7 +131,7 @@ int vector_reserve(vector me, int size)
*/ */
int vector_trim(vector me) 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) 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) 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) 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; return -EINVAL;
} }
if (me->offset + 1 >= me->space) { if (me->item_count + 1 >= me->item_capacity) {
const int new_space = (int) (me->space * RESIZE_RATIO); const int new_space = (int) (me->item_capacity * RESIZE_RATIO);
void *const temp = realloc(me->storage, new_space * me->data_size); void *const temp = realloc(me->data, new_space * me->bytes_per_item);
if (!temp) { if (!temp) {
return -ENOMEM; return -ENOMEM;
} }
me->storage = temp; me->data = temp;
me->space = new_space; me->item_capacity = new_space;
} }
if (index != me->offset) { if (index != me->item_count) {
memmove(me->storage + (index + 1) * me->data_size, memmove(me->data + (index + 1) * me->bytes_per_item,
me->storage + index * me->data_size, me->data + index * me->bytes_per_item,
(me->offset - index) * me->data_size); (me->item_count - index) * me->bytes_per_item);
} }
memcpy(me->storage + index * me->data_size, data, me->data_size); memcpy(me->data + index * me->bytes_per_item, data, me->bytes_per_item);
me->offset++; me->item_count++;
return 0; 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) 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) 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)) { if (vector_is_illegal_input(me, index)) {
return -EINVAL; return -EINVAL;
} }
me->offset--; me->item_count--;
memmove(me->storage + index * me->data_size, memmove(me->data + index * me->bytes_per_item,
me->storage + (index + 1) * me->data_size, me->data + (index + 1) * me->bytes_per_item,
(me->offset - index) * me->data_size); (me->item_count - index) * me->bytes_per_item);
return 0; return 0;
} }
@@ -272,10 +275,10 @@ int vector_remove_at(vector me, const int index)
*/ */
int vector_remove_last(vector me) int vector_remove_last(vector me)
{ {
if (me->offset == 0) { if (me->item_count == 0) {
return -EINVAL; return -EINVAL;
} }
me->offset--; me->item_count--;
return 0; 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)) { if (vector_is_illegal_input(me, index)) {
return -EINVAL; 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; 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) 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)) { if (vector_is_illegal_input(me, index)) {
return -EINVAL; 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; 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) 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) int vector_clear(vector me)
{ {
const int ret = vector_set_space(me, START_SPACE); const int ret = vector_set_space(me, START_SPACE);
me->offset = 0; me->item_count = 0;
return ret; return ret;
} }
@@ -395,8 +398,8 @@ int vector_clear(vector me)
*/ */
vector vector_destroy(vector me) vector vector_destroy(vector me)
{ {
free(me->storage); free(me->data);
me->storage = NULL; me->data = NULL;
free(me); free(me);
return NULL; return NULL;
} }