1 /* $NetBSD: genlist.c,v 1.4 2006/09/09 16:22:09 manu Exp $ */ 2 3 /* Id: genlist.c,v 1.2 2004/07/12 20:43:50 ludvigm Exp */ 4 5 /* 6 * Copyright (C) 2004 SuSE Linux AG, Nuernberg, Germany. 7 * Contributed by: Michal Ludvig <mludvig (at) suse.cz>, SUSE Labs 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the project nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <sys/queue.h> 38 39 #include "genlist.h" 40 41 struct genlist * 42 genlist_init (void) 43 { 44 struct genlist *new = calloc(sizeof(struct genlist), 1); 45 TAILQ_INIT(new); 46 return new; 47 } 48 49 struct genlist_entry * 50 genlist_insert (struct genlist *head, void *data) 51 { 52 struct genlist_entry *entry = calloc(sizeof(struct genlist_entry), 1); 53 entry->data = data; 54 TAILQ_INSERT_HEAD(head, entry, chain); 55 return entry; 56 } 57 58 struct genlist_entry * 59 genlist_append (struct genlist *head, void *data) 60 { 61 struct genlist_entry *entry = calloc(sizeof(struct genlist_entry), 1); 62 entry->data = data; 63 TAILQ_INSERT_TAIL(head, entry, chain); 64 return entry; 65 } 66 67 void * 68 genlist_foreach (struct genlist *head, genlist_func_t func, void *arg) 69 { 70 struct genlist_entry *p; 71 void *ret = NULL; 72 TAILQ_FOREACH(p, head, chain) { 73 ret = (*func)(p->data, arg); 74 if (ret) 75 break; 76 } 77 78 return ret; 79 } 80 81 void * 82 genlist_next (struct genlist *head, struct genlist_entry **buf) 83 { 84 struct genlist_entry *p; 85 86 if (head) 87 p = TAILQ_FIRST(head); 88 else 89 p = (buf && *buf) ? TAILQ_NEXT(*buf, chain) : NULL; 90 if (buf) 91 *buf = p; 92 return (p ? p->data : NULL); 93 } 94 95 void 96 genlist_free (struct genlist *head, genlist_freedata_t func) 97 { 98 struct genlist_entry *p; 99 100 while ((p = TAILQ_LAST(head, genlist)) != NULL) { 101 TAILQ_REMOVE(head, p, chain); 102 if (func) 103 func(p->data); 104 free(p); 105 } 106 free(head); 107 } 108 109 110 #if 0 111 /* Here comes the example... */ 112 struct conf { 113 struct genlist *l1, *l2; 114 }; 115 116 void * 117 print_entry(void *entry, void *arg) 118 { 119 if (!entry) 120 return NULL; 121 printf("%s\n", (char *)entry); 122 return NULL; 123 } 124 125 void 126 dump_list(struct genlist *head) 127 { 128 genlist_foreach(head, print_entry, NULL); 129 } 130 131 void 132 free_data(void *data) 133 { 134 printf ("removing %s\n", (char *)data); 135 } 136 137 int main() 138 { 139 struct conf *cf; 140 char *cp; 141 struct genlist_entry *gpb; 142 143 cf = calloc(sizeof(struct conf), 1); 144 cf->l1 = genlist_init(); 145 cf->l2 = genlist_init(); 146 147 genlist_insert(cf->l1, "Ahoj"); 148 genlist_insert(cf->l1, "Cau"); 149 genlist_insert(cf->l1, "Nazdar"); 150 genlist_insert(cf->l1, "Te buch"); 151 152 genlist_append(cf->l2, "Curak"); 153 genlist_append(cf->l2, "Kozy"); 154 genlist_append(cf->l2, "Pica"); 155 genlist_append(cf->l2, "Prdel"); 156 157 printf("List 2\n"); 158 dump_list(cf->l2); 159 printf("\nList 1\n"); 160 dump_list(cf->l1); 161 162 printf("\nList 2 - using genlist_next()\n"); 163 for (cp = genlist_next (cf->l2, &gpb); cp; cp = genlist_next (0, &gpb)) 164 printf("%s\n", cp); 165 166 printf("\nFreeing List 1\n"); 167 /* the data here isn't actually alloc'd so we would really call 168 * genlist_free (cf->l1, 0); but to illustrate the idea */ 169 genlist_free (cf->l1, free_data); 170 cf->l1 = 0; 171 172 return 0; 173 } 174 #endif 175