1 // This is a simple implementation of an elastic array class. It includes constructor and destructor
2 // methods, append and access methods, and that's about it. The memory allocation is very naive: whenever
3 // we are about to append beyond the size of the buffer, we double its size.
5 // Copyright (c) 2021-2022 by Art Cancro
7 // This program is open source software. Use, duplication, or disclosure
8 // is subject to the terms of the GNU General Public License, version 3.
14 #include "libcitadel.h"
16 // Constructor for elastic array
17 Array *array_new(size_t element_size) {
18 Array *newarr = malloc(sizeof(Array));
20 memset(newarr, 0, sizeof(Array));
22 newarr->element_size = element_size;
27 // Destructor for elastic array
28 void array_free(Array *arr) {
29 free(arr->the_elements);
34 // Append an element to an array (we already know the element size because it's in the data type)
35 void array_append(Array *arr, void *new_element) {
37 if (!arr) { // silently fail if they gave us a null array
41 if ( (arr->the_elements == NULL) || (arr->num_alloc == 0)) {
43 arr->num_elements = 0;
44 arr->the_elements = malloc(arr->element_size * arr->num_alloc);
45 if (arr->the_elements == NULL) {
51 if (arr->num_elements > arr->num_alloc) {
52 arr->num_alloc = arr->num_alloc * 2; // whenever we exceed the buffer size, we double it.
53 arr->the_elements = realloc(arr->the_elements, (arr->element_size * arr->num_alloc));
54 if (arr->the_elements == NULL) {
59 memcpy((arr->the_elements + ( (arr->num_elements-1) * arr->element_size )), new_element, arr->element_size);
63 // Return the element in an array at the specified index
64 void *array_get_element_at(Array *arr, int index) {
65 return (arr->the_elements + ( index * arr->element_size ));
69 // Return the number of elements in an array
70 int array_len(Array *arr) {
71 return arr->num_elements;
75 // Sort an array. We already know the element size and number of elements, so all we need is
76 // a sort function, which we will pass along to qsort().
77 void array_sort(Array *arr, int (*compar)(const void *, const void *)) {
78 qsort(arr->the_elements, arr->num_elements, arr->element_size, compar);
82 // Delete an element from an array
83 void array_delete_element_at(Array *arr, int index) {
85 if (index >= arr->num_elements) { // If the supplied index is out of bounds, return quietly.
89 if (index < 0) { // If the supplied index is invalid, return quietly.
95 if (index == arr->num_elements) { // If we deleted the element at the end, there's no more to be done.
99 memmove( // memmove() is supposed to be safer than memcpy()
100 (arr->the_elements + (index * arr->element_size)),
101 arr->the_elements + ((index+1) * arr->element_size),
102 (arr->num_elements - index) * arr->element_size