# HG changeset patch # User David Demelier # Date 1315422768 -7200 # Node ID 7360d752183e9a8b87a6062f1234648c9652fdc4 # Parent da47652b60c557fa53b80ba853a060f1c4cf62b7 Added lists.h: Manage linked lists using token concatenation to generate functions for a specified type of structure. At the moment only single linked list is supported. diff -r da47652b60c5 -r 7360d752183e lists.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lists.h Wed Sep 07 21:12:48 2011 +0200 @@ -0,0 +1,118 @@ +/* + * lists.h -- function to manipulate linked lists + * + * Copyright (c) 2011, David Demelier + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _LISTS_H_ +#define _LISTS_H_ + +/* + * Available function for single linked lists : + * + * refers to the prefix argument given to the LIST_IMPLEMENTS macro. + * all function will use this prefix to determine the correct function. + * + * refers to the data type used as template. + * + * o void slist__init(struct slist *sls); + * Initialize the `ls' list structure. + * + * o void slist__push(struct slist *sls, *var) + * Add the `var' to the beginning of the list, if the list is empty + * the tail also refers to the head. + * + * o void slist__pop(struct slist *sls) + * Remove the first element from the list. + * + * o void slist__after(struct slist *sls, *after, *var) + * Insert after the object referenced by `after'. + * + * o void slist__remove(struct slist *sls, *var) + * Remove the var element from the list. + * + * o *slist__head(const struct slist *sls) + * Returns the first list element. + */ + +struct slist { + int length; + void *head; +}; + +/* + * This declare prototype function, to prevent reimplementing function + * that already exists somewhere. + */ + +#define SLIST_HEADER(attr, prefix, type) \ +attr void slist_##prefix##_init(struct slist *); \ +attr void slist_##prefix##_push(struct slist *, type *); \ +attr void slist_##prefix##_pop(struct slist *); \ +attr void slist_##prefix##_after(struct slist *, type *, type *); \ +attr void slist_##prefix##_remove(struct slist *, type *); \ +attr type *slist_##prefix##_head(const struct slist *); + +/* + * Generate available function with the specified prefix. Name argument + * is the next pointer entry in the `type' structure used to go through + * the list. + */ + +#define SLIST_IMPLEMENTS(attr, prefix, type, field) \ +attr void \ +slist_##prefix##_init(struct slist *sls) \ +{ \ + sls->length = 0; \ + sls->head = NULL; \ +} \ + \ +attr void \ +slist_##prefix##_push(struct slist *sls, type *var) \ +{ \ + var->field = sls->head; \ + sls->head = var; \ + sls->length++; \ +} \ + \ +attr void \ +slist_##prefix##_pop(struct slist *sls) \ +{ \ + if (sls->head) { \ + sls->head = ((type *)sls->head)->field; \ + sls->length--; \ + } \ +} \ + \ +attr void \ +slist_##prefix##_after(struct slist *sls, type *after, type *var) \ +{ \ + var->field = after->field; \ + after->field = var; \ + sls->length++; \ +} \ + \ +attr type * \ +slist_##prefix##_head(const struct slist *sls) \ +{ \ + return (type *) sls->head; \ +} + +#define SLIST_FOREACH(list, entry, field) \ + for (entry = (list)->head; \ + entry; \ + entry = entry->field) + +#endif /* _LISTS_H_ */