--- /dev/null
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2020 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CORAX_ARRAY_H
+#define CORAX_ARRAY_H
+
+struct cx_array;
+
+int cx_array_new(size_t, struct cx_array**);
+int cx_array_free(struct cx_array*);
+int cx_array_set(struct cx_array*, const int, void *data);
+int cx_array_get(struct cx_array*, const int, void **dst);
+
+#endif /* CORAX_ARRAY_H */
--- /dev/null
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2020 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+struct cx_array {
+ void **data;
+ int size;
+ int used;
+};
+
+/*
+ * _array_grow() - Increase the size of a dynamic array
+ *
+ * SYNOPSIS
+ * int _array_grow(struct cx_array *array, int new_size);
+ *
+ * DESCRIPTION
+ * The _array_grow() function increases the size of the dynamic array pointed to by `array' so
+ * that it can hold `new_size' items. It is not guaranteed that the size of the array after this
+ * operation will be exactly `new_size', however it is guaranteed that the size will not be
+ * smaller than the desired size.
+ * This function may cause the contents of the array to be copied to a new memory location, so
+ * the caller must not make any assumptions about the internals of the array.
+ *
+ * RETURN VALUE
+ * This function will return zero upon success, or a negative error number in case of an error.
+ *
+ * ERRORS
+ * -EINVAL The values provided in `array' and/or `new_size' are invalid
+ * -ENOMEM There was not enough free memory to increase the size of the array
+ */
+static int _array_grow(struct cx_array *array, int new_size)
+{
+ int ret_val;
+ void *new_data;
+
+ ret_val = -EINVAL;
+
+ if(array && new_size > 0) {
+ new_data = malloc(sizeof(void*) * new_size);
+
+ if(new_data) {
+ memcpy(new_data, array->data, array->size * sizeof(void*));
+ memset(new_data + (array->size + 1) * sizeof(void*), 0,
+ (new_size - array->size) * sizeof(void*));
+
+ free(array->data);
+ array->data = new_data;
+ array->size = new_size;
+ }
+ }
+
+ return(ret_val);
+}
+
+/*
+ * cx_array_new() - Allocate a new dynamic array
+ *
+ * SYNOPSIS
+ * #include <corax/array.h>
+ * int cx_array_new(int initsize, struct cx_array **dst);
+ *
+ * DESCRIPTION
+ * The cx_array_new() function allocates a new dynamic array with enough space for `initsize'
+ * items. If the array was allocated successfully, the pointer pointed to by `dst' will be set
+ * to point to the new array.
+ *
+ * RETURN VALUE
+ * This function returns zero upon success, or a negative error number if an error has occured.
+ * In the case of an error, the value of `*dst' is undefined.
+ *
+ * ERRORS
+ * -EINVAL The values of `initsize' and/or `dst' are invalid
+ * -ENOMEM There was not enough memory to satisfy all memory allocations
+ */
+int cx_array_new(int initsize, struct cx_array **dst)
+{
+ struct cx_array *array;
+ int ret_val;
+
+ ret_val = -EINVAL;
+ array = NULL;
+
+ if(initsize > 0 && dst) {
+ ret_val = -ENOMEM;
+ array = malloc(sizeof(*array));
+
+ if(array) {
+ memset(array, 0, sizeof(*array));
+
+ array->data = malloc(sizeof(void*) * initsize);
+
+ if(array->data) {
+ memset(array->data, 0, sizeof(void*) * initsize);
+ array->size = initsize;
+ array->used = 0;
+
+ ret_val = 0;
+ }
+ }
+ }
+
+ if(ret_val < 0) {
+ if(array) {
+ if(array->data) {
+ free(array->data);
+ }
+
+ free(array);
+ }
+ } else {
+ *dst = array;
+ }
+
+ return(ret_val);
+}
+
+/*
+ * cx_array_free() - Release the memory occupied by a dynamic array
+ *
+ * SYNOPSIS
+ * #include <corax/array.h>
+ * int cx_array_free(struct cx_array *array);
+ *
+ * DESCRIPTION
+ * The cx_array_free() function releases the memory occupied by the dynamic array pointed to by
+ * `array'. This function will not touch any of the data stored inside of the array.
+ *
+ * RETURN VALUE
+ * This function returns zero upon success, or a negative error number if an error has occured.
+ *
+ * ERRORS
+ * -EINVAL The value of `array' is invalid
+ */
+int cx_array_free(struct cx_array *array)
+{
+ int ret_val;
+
+ ret_val = -EINVAL;
+
+ if(array) {
+ if(array->data) {
+ free(array->data);
+ }
+
+ free(array);
+
+ ret_val = 0;
+ }
+
+ return(ret_val);
+}
+
+/*
+ * cx_array_set() - Set the value of an element in a dynamic array
+ *
+ * SYNOPSIS
+ * #include <corax/array.h>
+ * int cx_array_set(struct cx_array *array, const int idx, void *data);
+ *
+ * DESCRIPTION
+ * The cx_array_set() function sets the element at position `idx' of the array `array' to `data'.
+ * If the size of the array is less than `idx', the array will be resized so that it can hold
+ * enough entries to perform the operation. If the array size is increased, it may be increased
+ * to hold more than `idx' entries.
+ *
+ * RETURN VALUE
+ * This function will return zero upon success, or a negative error number if an error has
+ * occured.
+ *
+ * ERRORS
+ * -EINVAL The values passed in `array' and/or `idx' are invalid
+ * -ENOMEM There was not enough free memory to perform the operation
+ */
+int cx_array_set(struct cx_array *array, const int idx, void *data)
+{
+ int ret_val;
+
+ ret_val = -EINVAL;
+
+ if(array && idx >= 0) {
+ if(array->size < idx) {
+ ret_val = _array_grow(array, idx);
+ } else {
+ ret_val = 0;
+ }
+
+ if(!ret_val) {
+ array->data[idx] = data;
+ }
+ }
+
+ return(ret_val);
+}
+
+/*
+ * cx_array_get() - Get the value of an element in a dynamic array
+ *
+ * SYNOPSIS
+ * #include <corax/array.h>
+ * int cx_array_get(struct cx_array *array, const int idx, void **dst);
+ *
+ * DESCRIPTION
+ * The cx_array_get() function retrieves the element stored at position `idx' of the array
+ * pointed to by `array' and adjusts the pointer pointed to by `dst' to point to the element.
+ *
+ * RETURN VALUE
+ * This function returns zero upon success, or a negative error number if an error has occured.
+ *
+ * ERRORS
+ * -EINVAL The arguments passed to this function are invalid
+ * -EOVERFLOW The value passed in `idx' would lead to an invalid array access
+ */
+int cx_array_get(struct cx_array *array, const int idx, void **dst)
+{
+ int ret_val;
+
+ ret_val = -EINVAL;
+
+ if(array && idx >= 0 && dst) {
+ if(array->size < idx) {
+ ret_val = -EOVERFLOW;
+ } else {
+ *dst = array->data[idx];
+ ret_val = 0;
+ }
+ }
+
+ return(ret_val);
+}