]> git.corax.cc Git - corax/commitdiff
libc: Add cx_array dynamic array type libc-next unstable
authorMatthias Kruk <m@m10k.eu>
Mon, 10 Aug 2020 06:57:48 +0000 (15:57 +0900)
committerMatthias Kruk <m@m10k.eu>
Mon, 10 Aug 2020 06:57:48 +0000 (15:57 +0900)
include/corax/array.h [new file with mode: 0644]
libc/Makefile
libc/array.c [new file with mode: 0644]

diff --git a/include/corax/array.h b/include/corax/array.h
new file mode 100644 (file)
index 0000000..c052725
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * 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 */
index 5092ddd4a7bf7393694c51f458719b92250178a9..f953d87ba17d9c345f84a19a44f843b1df342ece 100644 (file)
@@ -1,6 +1,6 @@
 OUTPUT = libc.a
 OBJECTS = syscall.o string.o signal.o start.o stdio.o string_ia32.o unistd.o spinlock.o stdlib.o \
-         heap.o
+         heap.o array.o
 PHONY = clean
 INCLUDES = -I../include -I..
 CFLAGS = -m32 -Wall -nostdlib -nodefaultlibs -nostartfiles -ffreestanding $(INCLUDES)
diff --git a/libc/array.c b/libc/array.c
new file mode 100644 (file)
index 0000000..d3b5c08
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * 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);
+}