I would like to use below code for general purpose dynamic array implementation in my future codes. Does that look fine?
array.h:
#include <stdlib.h>
/* This file describes structures and functions
for general purpose dynamic array.
*/
struct array {
void *data; /* Points to where the data is */
int numElements; /* Number of elements */
int sizeElem; /* Size of a single elements */
int capacity; /* Current total space in number of elements */
};
/* macros for accessing array internals */
#define array_index(ARRAY, INDEX) (void *)((unsigned)((ARRAY)->data)+(INDEX*((ARRAY)->sizeElem)))
#define array_len(ARRAY) (ARRAY)->numElements
#define array_cap(ARRAY) (ARRAY)->capacity
static inline void array_init(struct array *arr, int capacity, int sizeElem) {
arr->data = malloc(capacity * sizeElem);
arr->capacity = capacity;
arr->sizeElem = sizeElem;
arr->numElements = 0;
}
/* Add an element to array. Expand array if necessary. */
static inline void array_add(struct array *arr, void *data) {
if (arr->capacity <= arr->numElements) {
int new_capacity = 2 * arr->capacity;
arr->data = realloc(arr->data, new_capacity * arr->sizeElem);
arr->capacity = new_capacity;
}
memcpy(array_index(arr,arr->numElements), data, arr->sizeElem);
arr->numElements++;
}
/* Macro for traversing array elements. */
#define array_for_each(TYPE, ELEM, ARRAY) \
for (TYPE *ELEM=(ARRAY)->data; (ELEM - (TYPE *)(ARRAY)->data) < (ARRAY)->numElements; ELEM++)
/* Removes the element at given index and moves other elements if necessary. */
static inline void array_delete_index(struct array *arr, int index) {
int movables = arr->numElements - index - 1;
memcpy(array_index(arr, index),
(void *)((unsigned)array_index(arr, index) + arr->sizeElem),
movables * arr->sizeElem);
arr->numElements--;
}
/* If array capacity is too much compared to number of elements,
reduce array capacity
*/
static inline void array_free_capacity(struct array *arr) {
if (arr->capacity > 2*arr->numElements) {
int new_capacity = arr->capacity / 2;
arr->data = realloc(arr->data, new_capacity * arr->sizeElem);
arr->capacity = new_capacity;
}
}
/* Probably useless macro */
#define array_free(ARRAY) free((ARRAY)->data)
/* Search for an element and return an index if found. Otherwise, return -1
Comparison function should return 0 if two items should be considered equal.
*/
static inline int array_search(struct array *arr, void *target, int (*cmp)(void *first, void *second)) {
for(int i=0; i<arr->numElements; i++) {
if(cmp(array_index(arr, i), target) == 0) return i;
}
return -1;
}
/* Returns a pointer to the element at given index, if it doesn't
exist, return NULL
*/
static inline void *array_get_index(struct array *arr, int index) {
if (index > (arr->numElements - 1)) return NULL;
return array_index(arr, index);
}
Usage:
First, initialize the array with data type and initial array capacity measured in number of elements that the array can hold:
struct task {
char *task_name;
int task_id;
};
struct array my_tasks;
/* Define an dynamic array of struct tasks */
array_init(&my_tasks, 2, sizeof(struct task));
After that, functions in array.h can be used to add, remove, traverse array etc.