list.c revision 74a3f230
1b3307321Smrg/** ------------------------------------------------------------------------ 2b3307321Smrg This file contains routines for manipulating generic lists. 3b3307321Smrg Lists are implemented with a "harness". In other words, each 4b3307321Smrg node in the list consists of two pointers, one to the data item 5b3307321Smrg and one to the next node in the list. The head of the list is 6b3307321Smrg the same struct as each node, but the "item" ptr is used to point 7b3307321Smrg to the current member of the list (used by the first_in_list and 8b3307321Smrg next_in_list functions). 9b3307321Smrg 10b3307321SmrgCopyright 1994 Hewlett-Packard Co. 11b3307321SmrgCopyright 1996, 1998 The Open Group 12b3307321Smrg 13b3307321SmrgPermission to use, copy, modify, distribute, and sell this software and its 14b3307321Smrgdocumentation for any purpose is hereby granted without fee, provided that 15b3307321Smrgthe above copyright notice appear in all copies and that both that 16b3307321Smrgcopyright notice and this permission notice appear in supporting 17b3307321Smrgdocumentation. 18b3307321Smrg 19b3307321SmrgThe above copyright notice and this permission notice shall be included 20b3307321Smrgin all copies or substantial portions of the Software. 21b3307321Smrg 22b3307321SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 23b3307321SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24b3307321SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 25b3307321SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 26b3307321SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 27b3307321SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28b3307321SmrgOTHER DEALINGS IN THE SOFTWARE. 29b3307321Smrg 30b3307321SmrgExcept as contained in this notice, the name of The Open Group shall 31b3307321Smrgnot be used in advertising or otherwise to promote the sale, use or 32b3307321Smrgother dealings in this Software without prior written authorization 33b3307321Smrgfrom The Open Group. 34b3307321Smrg 35b3307321Smrg ----------------------------------------------------------------------- **/ 36b3307321Smrg 37b3307321Smrg#include <stdio.h> 38b3307321Smrg#include <stdlib.h> 39b3307321Smrg 40b3307321Smrg#include "list.h" 41b3307321Smrg 42b3307321Smrg 43b3307321Smrg/** ------------------------------------------------------------------------ 44b3307321Smrg Sets the pointers of the specified list to NULL. 45b3307321Smrg --------------------------------------------------------------------- **/ 46b3307321Smrgvoid zero_list(list_ptr lp) 47b3307321Smrg{ 48b3307321Smrg lp->next = NULL; 49b3307321Smrg lp->ptr.item = NULL; 50b3307321Smrg} 51b3307321Smrg 52b3307321Smrg 53b3307321Smrg/** ------------------------------------------------------------------------ 54b3307321Smrg Adds item to the list pointed to by lp. Finds the end of the 55b3307321Smrg list, then mallocs a new list node onto the end of the list. 56b3307321Smrg The item pointer in the new node is set to "item" passed in, 57b3307321Smrg and the next pointer in the new node is set to NULL. 58b3307321Smrg Returns 1 if successful, 0 if the malloc failed. 59b3307321Smrg -------------------------------------------------------------------- **/ 60b3307321Smrgint add_to_list(list_ptr lp, void *item) 61b3307321Smrg{ 62b3307321Smrg while (lp->next) { 63b3307321Smrg lp = lp->next; 64b3307321Smrg } 65b3307321Smrg if ((lp->next = (list_ptr) malloc( sizeof( list_item))) == NULL) { 66b3307321Smrg 67b3307321Smrg return 0; 68b3307321Smrg } 69b3307321Smrg lp->next->ptr.item = item; 70b3307321Smrg lp->next->next = NULL; 71b3307321Smrg 72b3307321Smrg return 1; 73b3307321Smrg} 74b3307321Smrg 75b3307321Smrg 76b3307321Smrg/** ------------------------------------------------------------------------ 7774a3f230Smrg Creates a new list and sets its pointers to NULL. 78b3307321Smrg Returns a pointer to the new list. 79b3307321Smrg -------------------------------------------------------------------- **/ 805e358ecaSmrglist_ptr new_list (void) 81b3307321Smrg{ 82b3307321Smrg list_ptr lp; 83b3307321Smrg 84b3307321Smrg if ((lp = (list_ptr) malloc( sizeof( list_item)))) { 85b3307321Smrg lp->next = NULL; 86b3307321Smrg lp->ptr.item = NULL; 87b3307321Smrg } 88b3307321Smrg 89b3307321Smrg return lp; 90b3307321Smrg} 91b3307321Smrg 92b3307321Smrg 93b3307321Smrg/** ------------------------------------------------------------------------ 94b3307321Smrg Creates a new list head, pointing to the same list as the one 95b3307321Smrg passed in. If start_at_curr is TRUE, the new list's first item 96b3307321Smrg is the "current" item (as set by calls to first/next_in_list()). 97b3307321Smrg If start_at_curr is FALSE, the first item in the new list is the 98b3307321Smrg same as the first item in the old list. In either case, the 99b3307321Smrg curr pointer in the new list is the same as in the old list. 100b3307321Smrg Returns a pointer to the new list head. 101b3307321Smrg -------------------------------------------------------------------- **/ 102b3307321Smrglist_ptr dup_list_head(list_ptr lp, int start_at_curr) 103b3307321Smrg{ 10474a3f230Smrg list_ptr new_listp; 105b3307321Smrg 10674a3f230Smrg if ((new_listp = (list_ptr) malloc( sizeof( list_item))) == NULL) { 107b3307321Smrg 108b3307321Smrg return (list_ptr)NULL; 109b3307321Smrg } 11074a3f230Smrg new_listp->next = start_at_curr ? lp->ptr.curr : lp->next; 11174a3f230Smrg new_listp->ptr.curr = lp->ptr.curr; 112b3307321Smrg 11374a3f230Smrg return new_listp; 114b3307321Smrg} 115b3307321Smrg 116b3307321Smrg 117b3307321Smrg/** ------------------------------------------------------------------------ 118b3307321Smrg Returns the number of items in the list. 119b3307321Smrg -------------------------------------------------------------------- **/ 120b3307321Smrgunsigned int list_length(list_ptr lp) 121b3307321Smrg{ 122b3307321Smrg unsigned int count = 0; 123b3307321Smrg 124b3307321Smrg while (lp->next) { 125b3307321Smrg count++; 126b3307321Smrg lp = lp->next; 127b3307321Smrg } 128b3307321Smrg 129b3307321Smrg return count; 130b3307321Smrg} 131b3307321Smrg 132b3307321Smrg 133b3307321Smrg/** ------------------------------------------------------------------------ 134b3307321Smrg Scans thru list, looking for a node whose ptr.item is equal to 135b3307321Smrg the "item" passed in. "Equal" here means the same address - no 136b3307321Smrg attempt is made to match equivalent values stored in different 137b3307321Smrg locations. If a match is found, that node is deleted from the 138b3307321Smrg list. Storage for the node is freed, but not for the item itself. 139b3307321Smrg Returns a pointer to the item, so the caller can free it if it 140b3307321Smrg so desires. If a match is not found, returns NULL. 141b3307321Smrg -------------------------------------------------------------------- **/ 142b3307321Smrgvoid *delete_from_list(list_ptr lp, void *item) 143b3307321Smrg{ 144b3307321Smrg list_ptr new_next; 145b3307321Smrg 146b3307321Smrg while (lp->next) { 147b3307321Smrg if (lp->next->ptr.item == item) { 148b3307321Smrg new_next = lp->next->next; 149b3307321Smrg free (lp->next); 150b3307321Smrg lp->next = new_next; 151b3307321Smrg 152b3307321Smrg return item; 153b3307321Smrg } 154b3307321Smrg lp = lp->next; 155b3307321Smrg } 156b3307321Smrg 157b3307321Smrg return NULL; 158b3307321Smrg} 159b3307321Smrg 160b3307321Smrg 161b3307321Smrg/** ------------------------------------------------------------------------ 162b3307321Smrg Deletes each node in the list *except the head*. This allows 163b3307321Smrg the deletion of lists where the head is not malloced or created 16474a3f230Smrg with new_list(). If free_items is true, each item pointed to 165b3307321Smrg from the node is freed, in addition to the node itself. 166b3307321Smrg -------------------------------------------------------------------- **/ 167b3307321Smrgvoid delete_list(list_ptr lp, int free_items) 168b3307321Smrg{ 169b3307321Smrg list_ptr del_node; 170b3307321Smrg void *item; 171b3307321Smrg 172b3307321Smrg while (lp->next) { 173b3307321Smrg del_node = lp->next; 174b3307321Smrg item = del_node->ptr.item; 175b3307321Smrg lp->next = del_node->next; 176b3307321Smrg free (del_node); 177b3307321Smrg if (free_items) { 178b3307321Smrg free( item); 179b3307321Smrg } 180b3307321Smrg } 181b3307321Smrg} 182b3307321Smrg 183b3307321Smrgvoid delete_list_destroying(list_ptr lp, void destructor(void *item)) 184b3307321Smrg{ 185b3307321Smrg list_ptr del_node; 186b3307321Smrg void *item; 187b3307321Smrg 188b3307321Smrg while (lp->next) { 189b3307321Smrg del_node = lp->next; 190b3307321Smrg item = del_node->ptr.item; 191b3307321Smrg lp->next = del_node->next; 192b3307321Smrg free( del_node); 193b3307321Smrg if (destructor) { 194b3307321Smrg destructor( item); 195b3307321Smrg } 196b3307321Smrg } 197b3307321Smrg} 198b3307321Smrg 199b3307321Smrg 200b3307321Smrg/** ------------------------------------------------------------------------ 201b3307321Smrg Returns a ptr to the first *item* (not list node) in the list. 202b3307321Smrg Sets the list head node's curr ptr to the first node in the list. 203b3307321Smrg Returns NULL if the list is empty. 204b3307321Smrg -------------------------------------------------------------------- **/ 205b3307321Smrgvoid * first_in_list(list_ptr lp) 206b3307321Smrg{ 207b3307321Smrg if (! lp) { 208b3307321Smrg 209b3307321Smrg return NULL; 210b3307321Smrg } 211b3307321Smrg lp->ptr.curr = lp->next; 212b3307321Smrg 213b3307321Smrg return lp->ptr.curr ? lp->ptr.curr->ptr.item : NULL; 214b3307321Smrg} 215b3307321Smrg 216b3307321Smrg/** ------------------------------------------------------------------------ 217b3307321Smrg Returns a ptr to the next *item* (not list node) in the list. 218b3307321Smrg Sets the list head node's curr ptr to the next node in the list. 219b3307321Smrg first_in_list must have been called prior. 220b3307321Smrg Returns NULL if no next item. 221b3307321Smrg -------------------------------------------------------------------- **/ 222b3307321Smrgvoid * next_in_list(list_ptr lp) 223b3307321Smrg{ 224b3307321Smrg if (! lp) { 225b3307321Smrg 226b3307321Smrg return NULL; 227b3307321Smrg } 228b3307321Smrg if (lp->ptr.curr) { 229b3307321Smrg lp->ptr.curr = lp->ptr.curr->next; 230b3307321Smrg } 231b3307321Smrg 232b3307321Smrg return lp->ptr.curr ? lp->ptr.curr->ptr.item : NULL; 233b3307321Smrg} 234b3307321Smrg 235b3307321Smrgint list_is_empty(list_ptr lp) 236b3307321Smrg{ 237b3307321Smrg return (lp == NULL || lp->next == NULL); 238b3307321Smrg} 239b3307321Smrg 240