To make your list data structure abstract, simply hide the definition of the node_ll
structure in a source file. The header file would only contain the forward declaration, and the prototypes for the APIs:
typedef struct node_ll node_ll;
typedef struct linkedlist { node_ll *head; } linkedlist;
static inline linkedlist make_linkedlist () {
const linkedlist zero_ll = { 0 };
return zero_ll;
}
void unmake_linkedlist (linkedlist *list);
void linkedlist_add (linkedlist *list, void *data);
void linkedlist_traverse_until (linkedlist *list,
int (*visit)(void *visit_data, void *data),
void *visit_data);
The linkedlist_traverse_until()
function will basically call the provided visit()
function on each node, unless visit()
returns 0, at which point it stops. The implementation of the function knows how to access a node_ll
because it is in the source file that has the complete definition of the struct node_ll
.
while (node) {
if (visit(visit_data, node->data)) {
node = node->next;
continue;
}
break;
}