From: Matthias Kruk Date: Mon, 10 Aug 2020 06:57:48 +0000 (+0900) Subject: libc: Add cx_array dynamic array type X-Git-Url: https://git.corax.cc/?a=commitdiff_plain;h=85bbad165ec49699185ad87db9060c9e04d876e6;p=corax libc: Add cx_array dynamic array type --- diff --git a/include/corax/array.h b/include/corax/array.h new file mode 100644 index 0000000..c052725 --- /dev/null +++ b/include/corax/array.h @@ -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 . + */ + +#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 */ diff --git a/libc/Makefile b/libc/Makefile index 5092ddd..f953d87 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -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 index 0000000..d3b5c08 --- /dev/null +++ b/libc/array.c @@ -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 . + */ + +#include +#include +#include + +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 + * 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 + * 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 + * 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 + * 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); +}