The LevAWC Project
 All Data Structures Files Functions Variables Typedefs Enumerations Macros Pages
slist.c
Go to the documentation of this file.
1 /*
2  * _____
3  * ANSI / ___/
4  * / /__
5  * \___/
6  *
7  * Filename: slist.c
8  * Author : Kyle Loudon/Dan Levin
9  * Date : Fri Mar 22 12:40:45 GMT 2013
10  * Version : 0.51
11  * ---
12  * Description: A singly-linked list - implemented as a pure, generic ADT.
13  *
14  * Revision history - coming up below:
15  *
16  * Date Revision message
17  * 2012-12-03 Created this file
18  * 2013-02-05 Made following changes to function 'int SLISTremnode(Slist list, void **data)':
19  * - Changed function name to - 'int SLISTfind_remove(Slist list, void **data)'
20  * - Changed return value - for missing "match-callback"(=not set) - from -1 to -2
21  * - Changed return value - for node not found - from -1 to 1.
22  * 2013-02-19 Made some revision to the Doxygen documentation. Enhanced the description of
23  * in/out parameters - i.e. double-pointers.
24  * 2015-03-31 This code ready for version 0.51
25  */
26 
32 #include "slist.h"
33 
34 struct SListElmt_
35 {
36  void *data;
37  struct SListElmt_ *next;
38 };
39 
40 struct SList_
41 {
42  int size;
43  int (*match)(const void *key1, const void *key2);
44  void (*destroy)(void *data);
45  struct SListElmt_ *head;
46  struct SListElmt_ *tail;
47 };
48 
49 
50 static void revert(SlistNode node);
51 static void bwd_traverse(SlistNode node, void (*callback)(const void *data));
52 
53 /* FUNCTION DEFINITIONS --------------------------------------------------- */
54 
55 Slist SLISTinit(void (*destroy)(void *data))
56 {
57  Slist list;
58 
59  if ((list = (Slist)malloc(sizeof(struct SList_)))==NULL)
60  return NULL;
61 
62  list->size = 0;
63  list->match = NULL;
64  list->destroy = destroy;
65  list->head = NULL;
66  list->tail = NULL;
67 
68  return list;
69 }
70 
71 void SLISTdestroy(Slist list)
72 {
73  void *data;
74 
75  while (SLISTsize(list) > 0)
76  {
77 
78  if (SLISTremnext(list, NULL, (void **)&data) == 0 && list->destroy !=
79  NULL)
80  list->destroy(data);
81  }
82  free(list);
83 }
84 
85 int SLISTinsnext(Slist list, SlistNode node, const void *data)
86 {
87  SlistNode newelement;
88 
89  if ((newelement = (SlistNode)malloc(sizeof(struct SListElmt_))) == NULL)
90  return -1;
91 
92  newelement->data = (void *)data;
93 
94  if (node == NULL)
95  {
96  if (list->size == 0)
97  list->tail = newelement;
98 
99  newelement->next = list->head;
100  list->head = newelement;
101  }
102 
103  else
104  {
105  if (node->next == NULL)
106  list->tail = newelement;
107 
108  newelement->next = node->next;
109  node->next = newelement;
110  }
111 
112  list->size++;
113 
114  return 0;
115 }
116 
117 int SLISTremnext(Slist list, SlistNode node, void **data)
118 {
119 
120  SlistNode oldelement;
121 
122  if (list->size == 0)
123  return -1;
124 
125  if (node == NULL)
126  {
127  *data = list->head->data;
128  oldelement = list->head;
129  list->head = list->head->next;
130 
131  if (list->size == 1) /* Changed according to errata 010607 */
132  list->tail = NULL;
133  }
134  else
135  {
136  if (node->next == NULL)
137  return -1;
138 
139  *data = node->next->data;
140  oldelement = node->next;
141  node->next = node->next->next;
142 
143  if (node->next == NULL)
144  list->tail = node;
145  }
146 
147  free(oldelement);
148 
149  list->size--;
150 
151  return 0;
152 }
153 
154 int SLISTsize(Slist list)
155 {
156  return list->size;
157 }
158 
160 {
161  return list->head;
162 }
163 
165 {
166  return list->tail;
167 }
168 
169 int SLISTishead(Slist list, SlistNode node)
170 {
171  return list->head==node ? 1 : 0;
172 }
173 
174 int SLISTistail(Slist list, SlistNode node)
175 {
176  return list->tail==node ? 1 : 0;
177 }
178 
179 void *SLISTdata(SlistNode node)
180 {
181  return node->data;
182 }
183 
185 {
186  return node->next;
187 }
188 
189 SlistNode SLISTfindnode(Slist list, const void *data)
190 {
191  SlistNode member = NULL;
192 
193  /* Match callback not set */
194  if (list->match == NULL)
195  return NULL;
196 
197  for (member = list->head; member != NULL; member = member->next)
198  {
199  if (list->match(data, SLISTdata(member)))
200  break;
201  }
202 
203  return member;
204 }
205 
206 int SLISTfind_remove(Slist list, void **data)
207 {
208  SlistNode member, prev;
209 
210  prev = NULL;
211 
212  /* If match-callback not set */
213  if (list->match == NULL)
214  return -2;
215 
216  /* Search list sequentially.. */
217  for (member = list->head; member != NULL; member = member->next)
218  {
219  if (list->match(*data, member->data))
220  break;
221 
222  prev = member;
223  }
224 
225  if (member == NULL) /* Node not found */
226  return 1;
227 
228  /* Perform the removal.. */
229  return SLISTremnext(list, prev, data);
230 }
231 
232 void SLISTsetmatch(Slist list, int (*match)(const void *key1, const void *key2))
233 {
234  list->match = match;
235 }
236 
238 {
239  return list->match;
240 }
241 
242 void SLISTreverse(Slist list)
243 {
244  SlistNode tmp;
245 
246  /* If listsize > 1... */
247  if (list->size > 1)
248  {
249  /* Call 'revert()' to reverse the list physically */
250  revert(list->head);
251  list->head->next = NULL;
252 
253  /* Swap head- and tailpointers */
254  tmp = list->head;
255  list->head = list->tail;
256  list->tail = tmp;
257  }
258 }
259 
260 static void revert(SlistNode node)
261 {
262  if (!(node->next))
263  return;
264 
265  revert(node->next);
266  node->next->next=node;
267 }
268 
269 /* Selection sort for linked list */
270 void SLISTsort(Slist list, int (*cmp)(const void *key1, const void *key2))
271 {
272  SlistNode curr, maxmin, tmp;
273  void *tmpdata;
274 
275  if (list->size > 1)
276  {
277  curr = list->head;
278 
279  while (curr->next)
280  {
281  maxmin = curr;
282  tmp = curr->next;
283 
284  while(tmp)
285  {
286  if (cmp(tmp->data, maxmin->data) < 0)
287  maxmin = tmp;
288  tmp = tmp->next;
289  }
290 
291  if (maxmin != curr)
292  {
293  tmpdata = curr->data;
294  curr->data = maxmin->data;
295  maxmin->data = tmpdata;
296  }
297  curr = curr->next;
298  }
299  }
300 }
301 
302 static void bwd_traverse(SlistNode node, void (*callback)(const void *data))
303 {
304  if (!(node))
305  return;
306 
307  bwd_traverse(node->next, callback);
308  callback(node->data);
309 }
310 
311 void SLISTtraverse(Slist list, void (*callback)(const void *data), int direction)
312 {
313  SlistNode curr;
314 
315  if (direction == SLIST_FWD)
316  for (curr=list->head; curr != NULL; curr=curr->next)
317  callback(curr->data);
318 
319  if (direction == SLIST_BWD)
320  {
321  curr = list->head;
322  bwd_traverse(curr, callback);
323  }
324 }