#ifndef LIST_H_INCLUDED #define LIST_H_INCLUDED /* * list.h * simple list package * all code is in this .h file so the complier can "inline" the code for * greater speed * * Author(s) * Scott A. Leerssen, leerssen@issl.atl.hp.com * * Protection Notice * Copyright (c) 1997, Scott Leerssen, All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #ifdef DMALLOC #include #else #include #endif #ifndef __GNUC__ #define inline /* I'm a crappy compiler */ #endif /* list data type */ typedef struct list { void *__ldata; struct list *__lprev; struct list *__lnext; } list_t; #ifdef __cplusplus extern "C" { #endif /* create a new list */ static inline list_t *list_new(void) { list_t *tmp = (list_t *)malloc(sizeof(list_t)); if (tmp == NULL) return NULL; tmp->__ldata = NULL; tmp->__lnext = tmp; tmp->__lprev = tmp; return tmp; } /* insert into a list after the pointed to list item */ static inline int list_insert(list_t *after, void *data) { list_t *newnode = (list_t *)malloc(sizeof(list_t)); if (newnode == NULL) return 1; newnode->__ldata = data; newnode->__lnext = after->__lnext; after->__lnext->__lprev = newnode; after->__lnext = newnode; newnode->__lprev = after; return 0; } /* delete the given element */ static inline int list_delete(list_t *element) { if ((element->__lprev == element->__lnext) && (element->__lnext == element)) { return 1; } element->__lprev->__lnext = element->__lnext; element->__lnext->__lprev = element->__lprev; free(element); return 0; } /* find the last element of a list */ static inline list_t *list_tail(list_t *list) { return(list->__lprev); } /* return a pointer to the actual last data element */ static inline void *tail_element(list_t *list) { return(list->__lprev->__ldata); } /* find the first list element */ static inline list_t *list_head(list_t *list) { return(list->__lnext); } /* return a pointer to the actual first data element*/ static inline void *head_element(list_t *list) { return(list->__lnext->__ldata); } /* return a pointer to the data of a given list pointer */ static inline void *data_element(list_t *list) { return(list->__ldata); } /* is the list empty? */ static inline int list_empty(list_t *list) { return(list->__lnext == list); } /* get the next list item */ static inline list_t *list_next(list_t *list) { return(list->__lnext); } /* free the list structures, leaves the data alone */ static inline void list_free(list_t *list) { while(!list_empty(list)) { list_delete(list->__lnext); } free(list); } /* search a list and apply a function (also works as a list search) */ /* * here is a code sample so any moron should be able to use this stuff * * a structure that __data will point to: * typedef struct { * int fd; * int type; * } fds_info_t; * * our list of strutures: * static list_t *fd_list_p; * * a compare function which returns a zero/non-zero value * static int fd_cmp(fds_info_t * info_p, va_list ap) * { * int fd1, fd2; * * fd1 = info_p->fd; * fd2 = va_arg(ap, int); * return(fd1 == fd2); * } * * a locator function which returns to the caller a pointer to the * matching element * static list_t *locate_fd(int fd) * { * list_t *p = fd_list_p; * * if (p == NULL) { * return(NULL); * } * if ((p = list_apply(p, (int(*)(void*,char*))fd_cmp, fd)) == fd_list_p) { * return(NULL); * } else { * return(p); * } * } * * a function that returns the type field of the fds_info_t structure * int fds_type(int fd) * { * list_t *p; * * if ((p = locate_fd(fd)) == NULL) { * return(FDS_NOT_FOUND); * } * return(((fds_info_t *)(p->__ldata))->type); * } * */ typedef int func_arg(void *, va_list); static /* var args functions can not be inline */ list_t *list_apply(list_t *list, func_arg *func, ...) { va_list ap; list_t *cur = list->__lnext; va_start(ap, func); while(cur != list) { if ( func(cur->__ldata, ap) ) { break; } cur = cur->__lnext; } va_end(ap); return(cur); } /* These are a two part macro for doing your own list looping while still */ /* maintaining "somewhat" of a list data abstraction from your code. */ /* The idea is that if you just want to do a few little things with each */ /* element of a list, you can uses these instead of list_apply() and */ /* not have to write the small function list_apply() would require. */ #define FOREACH(list, data_type, data_ptr) \ { /* foreach scope */ \ list_t *__lptr = list_head(list); \ while (__lptr != list) { \ data_ptr = (data_type *)__lptr->__ldata; /* end the above marco */ #define ENDEACH \ __lptr = __lptr->__lnext; \ } /* end while */ \ } /* end foreach scop */ #ifdef __cplusplus } #endif #endif /* LIST_H_INCLUDED */