Skip to content

Instantly share code, notes, and snippets.

@DenisBelmondo
Created June 11, 2023 22:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DenisBelmondo/35b5f81a70fed81ee8a0e69a9df8f88b to your computer and use it in GitHub Desktop.
Save DenisBelmondo/35b5f81a70fed81ee8a0e69a9df8f88b to your computer and use it in GitHub Desktop.
C dynamic array implementation
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
struct ListInfo;
struct List;
typedef void *(*alloc_item_func_t)(struct ListInfo *, struct List *);
typedef void (*free_item_func_t) (struct ListInfo *, struct List *, size_t);
typedef void (*free_data_func_t) (struct ListInfo *, struct List *);
struct ListInfo {
size_t item_size;
alloc_item_func_t alloc_item;
free_item_func_t free_item;
free_data_func_t free_data;
};
struct List {
void **data;
size_t count;
size_t cap;
struct ListInfo *info;
};
void *ListInfo_alloc_item_default(struct ListInfo *info, struct List *list) {
return malloc(info->item_size);
}
void ListInfo_free_item_default(struct ListInfo *info, struct List *list, size_t index) {
free(list->data[index]);
list->data[index] = NULL;
}
void ListInfo_free_data_default(struct ListInfo *info, struct List *list) {
free(list->data);
list->data = NULL;
}
void ListInfo_init(struct ListInfo *info, size_t item_size) {
struct ListInfo i = {
.alloc_item = &ListInfo_alloc_item_default,
.free_data = &ListInfo_free_data_default,
.free_item = &ListInfo_free_item_default,
.item_size = item_size,
};
*info = i;
}
void List_init(struct List *list, struct ListInfo *info) {
struct List l = {
list->data = NULL,
list->count = 0,
list->cap = 0,
list->info = info,
};
*list = l;
}
void List_push_back(struct List *list, void *item) {
if (!list->data) {
list->data = (void **)malloc(sizeof(void *) * 10);
goto push_item;
}
if (list->count >= list->cap) {
size_t new_cap = list->cap + 10;
list->data = (void **)realloc(list->data, new_cap * sizeof (void *));
list->cap = new_cap;
goto push_item;
}
push_item:
list->count++;
list->data[list->count - 1] = item;
}
void List_insert(struct List *list, size_t index, void *item) {
if (!list->data) {
list->data = (void **)malloc(sizeof(void *) * 10);
}
// move in place
void **dest = list->data;
bool must_realloc = list->count >= list->cap;
if (must_realloc) {
size_t new_cap = list->cap + 10;
dest = (void **)malloc(new_cap * sizeof (void *));
}
// copy data from index to the end
memcpy(dest + index + 1, list->data + index, list->count - index);
dest[index] = item;
memcpy(dest, list->data, index); // copy data up to index
if (must_realloc) {
list->data = dest;
}
list->count++;
}
void List_free_items(struct List *list) {
if (!list->info->free_item) {
return;
}
for (size_t i = 0; i < list->count; i++) {
list->info->free_item(list->info, list, i);
}
}
void List_free_data(struct List *list) {
list->info->free_data(list->info, list);
}
int main(int argc, char **argv) {
struct ListInfo li;
struct List l;
ListInfo_init(&li, sizeof (int));
List_init(&l, &li);
int v = 123;
int v2 = 94;
List_insert(&l, 0, &v2);
for (size_t i = 0; i < l.count; i++) {
printf("%d\n", *(int *)l.data[i]);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment