list.c (2873B)
1 /* 2 * Copyright (c) 2023 Jacob R. Edwards <jacob@jacobedwards.org> 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include <stdlib.h> 18 19 #include "list.h" 20 21 struct item * 22 newitem(void *data) 23 { 24 struct item *item; 25 26 item = calloc(1, sizeof(*item)); 27 if (!item) 28 return NULL; 29 30 item->data = data; 31 return item; 32 } 33 34 void 35 freeitem(struct item *item) 36 { 37 free(item); 38 } 39 40 struct list * 41 newlist(void (*freedata)(void *)) 42 { 43 struct list *list; 44 45 list = calloc(1, sizeof(*list)); 46 if (!list) 47 return NULL; 48 49 list->freedata = freedata; 50 return list; 51 } 52 53 void 54 freelist(struct list *list) 55 { 56 struct item *item, *nextitem; 57 58 if (!list) 59 return; 60 61 for (item = list->items; item; item = nextitem) { 62 nextitem = item->next; 63 if (list->freedata) 64 list->freedata(item->data); 65 freeitem(item); 66 } 67 free(list); 68 } 69 70 /* 71 * The linkitem and unlinkitem functions are provided so that you 72 * may choose not to use the list struct. Unfortunatly I couldn't 73 * think of sane names which tell of this difference from the add 74 * and remove item functions. 75 */ 76 void 77 linkitem(struct item *item, struct item *to) 78 { 79 /* This function could check 80 * if (item->next || item->prev) 81 * and 82 * abort(); 83 * or return an error, but it does not. Maybe it should? 84 */ 85 86 item->next = to->next; 87 if (item->next) 88 item->next->prev = item; 89 item->prev = to; 90 if (to) 91 to->next = item; 92 } 93 94 void 95 unlinkitem(struct item *item) 96 { 97 if (item->next) 98 item->next->prev = item->prev; 99 if (item->prev) 100 item->prev->next = item->next; 101 item->next = item->prev = NULL; 102 } 103 104 void 105 additem(struct item *item, struct list *list, struct item *pos) 106 { 107 if (pos) { 108 linkitem(item, pos); 109 if (pos == list->last) 110 list->last = item; 111 } else { 112 if (!list->items) 113 list->last = item; 114 item->prev = NULL; 115 item->next = list->items; 116 if (item->next) 117 item->next->prev = item; 118 list->items = item; 119 } 120 } 121 122 void 123 removeitem(struct item *item, struct list *list) 124 { 125 if (item == list->items) 126 list->items = item->next; 127 if (item == list->last) 128 list->last = item->prev; 129 unlinkitem(item); 130 } 131 132 void 133 deleteitem(struct item *item, struct list *list) 134 { 135 removeitem(item, list); 136 if (list->freedata) 137 list->freedata(item->data); 138 freeitem(item); 139 }