1 /*
2 $Id: ll.c,v 1.1 2005/05/29 08:24:05 airborne Exp $
3
4 Copyright (C) 2005 Kris Verbeeck <airborne@advalvas.be>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public
17 License along with this library; if not, write to the
18 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
20 */
21
22
23 #include <stdlib.h>
24
25 #include "cddb/ll.h"
26
27
28 /* --- type and structure definitions */
29
30
31 /**
32 * Linked list element.
33 */
34 struct elem_s {
35 struct elem_s *prev; /**< previous element */
36 struct elem_s *next; /**< next element */
37 void *data; /**< the actual data of the element */
38 };
39
40 struct list_s {
41 int cnt; /**< number of elements in the list */
42 elem_destroy_cb *free_data; /**< callback used to free element data */
43 elem_t *first; /**< the first element in the list */
44 elem_t *last; /**< the last element in the list */
45 elem_t *it; /**< iterator element */
46 };
47
48
49 /* --- private prototypes */
50
51
52 static elem_t *elem_construct(void *data);
53
54 /**
55 * @return The next element.
56 */
57 static elem_t *elem_destroy(elem_t *elem, elem_destroy_cb *cb);
58
59
60 /* --- private functions */
61
62
elem_construct(void * data)63 static elem_t *elem_construct(void *data)
64 {
65 elem_t *elem;
66
67 elem = (elem_t*)calloc(1, sizeof(elem_t));
68 elem->data = data;
69 return elem;
70 }
71
elem_destroy(elem_t * elem,elem_destroy_cb * cb)72 static elem_t *elem_destroy(elem_t *elem, elem_destroy_cb *cb)
73 {
74 elem_t *next = NULL;
75
76 if (elem) {
77 next = elem->next;
78 if (cb) {
79 cb(elem->data);
80 }
81 free(elem);
82 }
83 return next;
84 }
85
86
87 /* --- construction / destruction */
88
89
list_new(elem_destroy_cb * cb)90 list_t *list_new(elem_destroy_cb *cb)
91 {
92 list_t *list;
93
94 list = (list_t*)calloc(1, sizeof(list_t));
95 list->free_data = cb;
96 return list;
97 }
98
list_destroy(list_t * list)99 void list_destroy(list_t *list)
100 {
101 list_flush(list);
102 if (list) {
103 free(list);
104 }
105 }
106
list_flush(list_t * list)107 void list_flush(list_t *list)
108 {
109 elem_t *elem;
110
111 if (list) {
112 elem = list->first;
113 while (elem) {
114 elem = elem_destroy(elem, list->free_data);
115 }
116 list->first = list->last = NULL;
117 list->cnt = 0;
118 }
119 }
120
121
122 /* --- list elements --- */
123
124
element_data(elem_t * elem)125 void *element_data(elem_t *elem)
126 {
127 if (elem) {
128 return elem->data;
129 }
130 return NULL;
131 }
132
133
134 /* --- getters & setters --- */
135
136
list_append(list_t * list,void * data)137 elem_t *list_append(list_t *list, void *data)
138 {
139 elem_t *elem = NULL;
140
141 if (list) {
142 elem = elem_construct(data);
143 if (elem) {
144 if (list->cnt == 0) {
145 list->first = list->last = elem;
146 } else {
147 list->last->next = elem;
148 elem->prev = list->last;
149 list->last = elem;
150 }
151 list->cnt++;
152 }
153 }
154 return elem;
155 }
156
list_size(list_t * list)157 int list_size(list_t *list)
158 {
159 if (list) {
160 return list->cnt;
161 }
162 return 0;
163 }
164
list_get(list_t * list,int idx)165 elem_t *list_get(list_t *list, int idx)
166 {
167 elem_t *elem = NULL;
168
169 if (list) {
170 if ((idx >= 0) && (idx < list->cnt)) {
171 elem = list->first;
172 while (idx) {
173 elem = elem->next;
174 idx--;
175 }
176 }
177 }
178 return elem;
179 }
180
list_first(list_t * list)181 elem_t *list_first(list_t *list)
182 {
183 if (list) {
184 list->it = list->first;
185 return list->it;
186 }
187 return NULL;
188 }
189
list_next(list_t * list)190 elem_t *list_next(list_t *list)
191 {
192 if (list) {
193 if (list->it) {
194 list->it = list->it->next;
195 }
196 return list->it;
197 }
198 return NULL;
199 }
200
201
202 /* --- iteration */
203