I want to use it when some function needs to return a list of something. Is it working as I think it should or is there undefined behavior somewhere? What I really tried to achieve is something like a templated <list> from C++ - for any type. I'm not sure if there is a standard solution/include/library for this.
list.h
#pragma once
#include <stddef.h>
struct list_handler
{
struct list_node *head;
struct list_node *tail;
size_t count;
};
struct list_node
{
void *data;
struct list_node *next;
};
void list_init(struct list_handler *list);
void list_add(struct list_handler *list, void *data);
void list_free(struct list_handler *list);
void list_foreach(struct list_handler *list, void (*foreach_function)(void *));
list.c
#include "list.h"
#include <stdlib.h>
void list_init(struct list_handler *list)
{
list->head = NULL;
list->tail = NULL;
list->count = 0;
}
void list_add(struct list_handler *list, void *data)
{
struct list_node *new_node = malloc(sizeof(struct list_node));
new_node->data = data;
new_node->next = NULL;
if (list->count > 0)
{
list->tail->next = new_node;
}
else
{
list->head = new_node;
}
list->tail = new_node;
++list->count;
}
void list_free(struct list_handler *list)
{
struct list_node *current = list->head;
struct list_node *previous;
while (current != NULL)
{
previous = current;
current = current->next;
free(current);
list->head = current;
--list->count;
}
list->tail = NULL;
}
void list_foreach(struct list_handler *list, void (*foreach_function)(void *))
{
struct list_node *current = list->head;
while (current != NULL)
{
(*foreach_function)(current->data);
current = current->next;
}
}
Usage:
void list_print(void *data)
{
int *temp = (int*) data;
printf("%d\n", *temp);
}
void list_free_data(void *data)
{
int *temp = (int*) data;
free(temp);
data = NULL;
}
int main(int argc, char *argv[])
{
struct list_handler list;
list_init(&list);
for (size_t i = 0; i < 3; ++i)
{
int *data = malloc(sizeof(int));
*data = i;
list_add(&list, data);
}
list_foreach(&list, list_print);
list_foreach(&list, list_free_data);
list_free(&list);
return 0;
}