Created
June 11, 2023 22:55
-
-
Save DenisBelmondo/35b5f81a70fed81ee8a0e69a9df8f88b to your computer and use it in GitHub Desktop.
C dynamic array implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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