1 /**
2 * collectd - src/utils_llist.c
3 * Copyright (C) 2006 Florian Forster <octo at collectd.org>
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * Florian Forster <octo at collectd.org>
25 */
27 #include "config.h"
29 #include <stdlib.h>
30 #include <string.h>
32 #include "utils_llist.h"
34 /*
35 * Private data types
36 */
37 struct llist_s
38 {
39 llentry_t *head;
40 llentry_t *tail;
41 int size;
42 };
44 /*
45 * Public functions
46 */
47 llist_t *llist_create (void)
48 {
49 llist_t *ret;
51 ret = calloc (1, sizeof (*ret));
52 if (ret == NULL)
53 return (NULL);
55 return (ret);
56 }
58 void llist_destroy (llist_t *l)
59 {
60 llentry_t *e_this;
61 llentry_t *e_next;
63 if (l == NULL)
64 return;
66 for (e_this = l->head; e_this != NULL; e_this = e_next)
67 {
68 e_next = e_this->next;
69 llentry_destroy (e_this);
70 }
72 free (l);
73 }
75 llentry_t *llentry_create (char *key, void *value)
76 {
77 llentry_t *e;
79 e = malloc (sizeof (*e));
80 if (e)
81 {
82 e->key = key;
83 e->value = value;
84 e->next = NULL;
85 }
87 return (e);
88 }
90 void llentry_destroy (llentry_t *e)
91 {
92 free (e);
93 }
95 void llist_append (llist_t *l, llentry_t *e)
96 {
97 e->next = NULL;
99 if (l->tail == NULL)
100 l->head = e;
101 else
102 l->tail->next = e;
104 l->tail = e;
106 ++(l->size);
107 }
109 void llist_prepend (llist_t *l, llentry_t *e)
110 {
111 e->next = l->head;
112 l->head = e;
114 if (l->tail == NULL)
115 l->tail = e;
117 ++(l->size);
118 }
120 void llist_remove (llist_t *l, llentry_t *e)
121 {
122 llentry_t *prev;
124 if ((l == NULL) || (e == NULL))
125 return;
127 prev = l->head;
128 while ((prev != NULL) && (prev->next != e))
129 prev = prev->next;
131 if (prev != NULL)
132 prev->next = e->next;
133 if (l->head == e)
134 l->head = e->next;
135 if (l->tail == e)
136 l->tail = prev;
138 --(l->size);
139 }
141 int llist_size (llist_t *l)
142 {
143 return (l ? l->size : 0);
144 }
146 static int llist_strcmp (llentry_t *e, void *ud)
147 {
148 if ((e == NULL) || (ud == NULL))
149 return (-1);
150 return (strcmp (e->key, (const char *)ud));
151 }
153 llentry_t *llist_search (llist_t *l, const char *key)
154 {
155 return (llist_search_custom (l, llist_strcmp, (void *)key));
156 }
158 llentry_t *llist_search_custom (llist_t *l,
159 int (*compare) (llentry_t *, void *), void *user_data)
160 {
161 llentry_t *e;
163 if (l == NULL)
164 return (NULL);
166 e = l->head;
167 while (e != NULL) {
168 llentry_t *next = e->next;
170 if (compare (e, user_data) == 0)
171 break;
173 e = next;
174 }
176 return (e);
177 }
179 llentry_t *llist_head (llist_t *l)
180 {
181 if (l == NULL)
182 return (NULL);
183 return (l->head);
184 }
186 llentry_t *llist_tail (llist_t *l)
187 {
188 if (l == NULL)
189 return (NULL);
190 return (l->tail);
191 }