Generic linked list in C using sys/queue.h

It is frequently required to use linked list in C language.
There is a popular generic list like “list in Linux Kernel”, but it is published with GPL license so prohibited to be used in closed source projects.

Hence we implement lists by ourselves or use sys/queue.h on Linux environment.
However the list in sys/queue.h is not that convenient to be used as itself.
It is lack of some operations like deletion, clearing and sorting.

So here we have some useful macros implemented here:

LIST_DEL ( listelm, elem, field ) - delete an element of the list

LIST_CLEAR ( listelm, entry_type, field ) - clear out the whole list elements

LIST_SORT ( listelm, entry_type, field, cmp_func ) - list heap sort by 'data_name'

LIST_EXISTS( listelm, entry_type, field, data_name, search_for, result_entry )
- find the list element with a certain data and put the element to 'result_entry'

LIST_PRINT ( listelm, entry_type, field, print_func )
- find the list element with a certain data and put the element to 'result_entry'

We enjoy the list in simpler way like “list_sample.c” below, which presents the sample code how to use theses macros.

#include <stdio.h>
#include <stdlib.h>
#include "sys_queue_list.h"

LIST_HEAD( sample_list, sample_entry );
struct sample_entry{
	int	data;
	LIST_ENTRY(sample_entry) list;
};

static inline struct sample_entry *list_put( struct sample_list *head, int input )
{
	struct sample_entry *new_node = calloc( 1, sizeof( struct sample_entry ) );
	new_node->data = input;
	LIST_INSERT_HEAD( head, new_node, list );
	return new_node;
}

static inline int smpl_cmp( struct sample_entry* a, struct sample_entry *b ){
	return a->data - b->data;
}

static inline void smpl_print( struct sample_entry* a ){
	printf("%d", a->data);
}

int main(void){
	struct sample_list head;
	struct sample_entry *result_node;

	LIST_INIT( &head );

	list_put( &head, 1 ); list_put( &head, 2 ); list_put( &head, 3 );
	list_put( &head, 4 ); list_put( &head, 5 ); list_put( &head, 6 );

	LIST_PRINT( &head, struct sample_entry, list, smpl_print );

	LIST_EXISTS( &head, struct sample_entry, list, data, 3, result_node );
	if( result_node ){
		printf( "\n 3 exists. Delete the entry. \n" );
		LIST_DEL( &head, result_node, list );
		LIST_PRINT( &head, struct sample_entry, list, smpl_print );
	}

	LIST_EXISTS( &head, struct sample_entry, list, data, 3, result_node );
	if( result_node ){
		printf( "\n 3 exists. Delete the entry \n" );
		LIST_DEL( &head, result_node, list );
		LIST_PRINT( &head, struct sample_entry, list, smpl_print );
	}

	LIST_SORT( &head, struct sample_entry, list, smpl_cmp );

	LIST_PRINT( &head, struct sample_entry, list, smpl_print );

	LIST_CLEAR( &head, struct sample_entry, list );

	LIST_PRINT( &head, struct sample_entry, list, smpl_print );

	return 0;
}

To use the macro functions, you can refer to
https://github.com/Geono/generic-linked-List-in-c
and download sys_queue_listop.h.

Leave a comment