00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <stdlib.h>
00025 #include <assert.h>
00026
00027 #include "slist.h"
00028 #include "xmalloc.h"
00029
00030
00031 static void
00032 _nop (void *data)
00033 {
00034
00035 }
00036
00037
00038 static inline int
00039 _simple_compare (const void *data, const void *compare)
00040 {
00041 return data == compare;
00042 }
00043
00044
00045 void
00046 slist_init (slist * s)
00047 {
00048 assert (s);
00049 s->head = 0;
00050 s->tail = 0;
00051 }
00052
00053
00054 void
00055 slist_delete_special (slist * s, void (*func) (void *))
00056 {
00057 slist_e *tmp;
00058 assert (s);
00059
00060 while (s->head)
00061 {
00062 func (s->head->data);
00063 tmp = s->head;
00064 s->head = s->head->next;
00065 free (tmp);
00066 }
00067 }
00068
00069
00070 void
00071 slist_delete (slist * s)
00072 {
00073 assert (s);
00074 slist_delete_special (s, free);
00075 }
00076
00077
00078 void
00079 slist_delete_list_only (slist * s)
00080 {
00081 assert (s);
00082 slist_delete_special (s, _nop);
00083 }
00084
00085
00086 void *
00087 slist_first (const slist * s)
00088 {
00089 assert (s);
00090 return s->head ? s->head->data : 0;
00091 }
00092
00093
00094 void *
00095 slist_last (const slist * s)
00096 {
00097 assert (s);
00098 return s->tail ? s->tail->data : 0;
00099 }
00100
00101
00102 void *
00103 slist_at_iter (slist_iter iter)
00104 {
00105 return iter.curr ? iter.curr->data : 0;
00106 }
00107
00108
00109 void
00110 slist_prepend (slist * s, void *data)
00111 {
00112 slist_e *newelem = xmalloc (sizeof (slist_e));
00113 assert (s);
00114
00115 newelem->next = s->head;
00116 newelem->data = data;
00117 s->head = newelem;
00118 }
00119
00120
00121 void
00122 slist_append (slist *s, void *data)
00123 {
00124 slist_e *newelem = xmalloc (sizeof (slist_e));
00125 assert (s);
00126
00127 newelem->next = 0;
00128 newelem->data = data;
00129
00130 if (s->tail)
00131 s->tail->next = newelem;
00132 else
00133 s->head = newelem;
00134
00135 s->tail = newelem;
00136 }
00137
00138
00139 void
00140 slist_insert (slist *s, slist_iter *iter, void *data)
00141 {
00142 assert (s);
00143 assert (iter);
00144
00145 if (!iter->prev)
00146 {
00147 slist_prepend (s, data);
00148 iter->prev = s->head;
00149 }
00150 else if (!iter->curr)
00151 {
00152 slist_append (s, data);
00153 iter->prev = s->tail;
00154 }
00155 else
00156 {
00157 slist_e *newelem = xmalloc (sizeof (slist_e));
00158
00159 newelem->next = iter->curr;
00160 iter->prev->next = newelem;
00161 iter->prev = newelem;
00162 newelem->data = data;
00163 }
00164 }
00165
00166
00167 void*
00168 slist_remove_first (slist *s)
00169 {
00170 void *removed_data = 0;
00171 slist_e *tmp;
00172 assert (s);
00173
00174 if (s->head)
00175 {
00176 removed_data = s->head->data;
00177 tmp = s->head->next;
00178 free (s->head);
00179 s->head = tmp;
00180
00181 if (!s->head)
00182 s->tail = 0;
00183 }
00184
00185 return removed_data;
00186 }
00187
00188
00189 void*
00190 slist_remove_last (slist *s)
00191 {
00192 void *removed_data = 0;
00193 slist_e *tmp;
00194 assert (s);
00195
00196 if (s->tail)
00197 {
00198 removed_data = s->tail->data;
00199 if (s->head == s->tail)
00200 {
00201 free (s->tail);
00202 s->head = 0;
00203 s->tail = 0;
00204
00205 return removed_data;
00206 }
00207 tmp = s->head;
00208
00209 while (tmp->next != s->tail)
00210 tmp = tmp->next;
00211
00212 tmp->next = 0;
00213 free (s->tail);
00214 s->tail = tmp;
00215 }
00216
00217 return removed_data;
00218 }
00219
00220
00221 void*
00222 slist_remove_at_iter (slist *s, slist_iter iter)
00223 {
00224 void *removed_data = 0;
00225 assert (s);
00226
00227 if (!iter.curr)
00228 return removed_data;
00229
00230 removed_data = iter.curr->data;
00231 if (!iter.prev)
00232 {
00233 slist_remove_first (s);
00234 }
00235 else
00236 {
00237 iter.prev->next = iter.curr->next;
00238 if (iter.curr == s->tail)
00239 s->tail = iter.prev;
00240
00241 free (iter.curr);
00242 }
00243
00244 return removed_data;
00245 }
00246
00247
00248 slist_iter
00249 slist_begin_iter (const slist *s)
00250 {
00251 slist_iter begin;
00252 assert (s);
00253
00254 begin.curr = s->head;
00255 begin.prev = 0;
00256
00257 return begin;
00258 }
00259
00260
00261 slist_iter
00262 slist_end_iter (const slist *s)
00263 {
00264 slist_iter end;
00265 assert (s);
00266
00267 end.curr = 0;
00268 end.prev = s->tail;
00269
00270 return end;
00271 }
00272
00273
00274 void *
00275 slist_iter_and_next (slist_iter *iter)
00276 {
00277 void *prev_data = 0;
00278 assert (iter);
00279
00280 if (iter->curr)
00281 {
00282 prev_data = iter->curr->data;
00283 iter->prev = iter->curr;
00284 iter->curr = iter->curr->next;
00285 }
00286
00287 return prev_data;
00288 }
00289
00290
00291 void
00292 slist_for_each (const slist * s, void (*func) (void *data, void* userdata),
00293 void *userdata)
00294 {
00295 assert (s);
00296 assert (func);
00297
00298 slist_for_each_range (slist_begin_iter (s), slist_end_iter (s),
00299 func, userdata);
00300 }
00301
00302
00303 void
00304 slist_for_each_range (slist_iter begin, slist_iter end,
00305 void (*func) (void *data, void* userdata),
00306 void *userdata)
00307 {
00308 slist_e *elem = begin.curr;
00309 assert (func);
00310
00311 if (elem)
00312 {
00313 while (elem != end.curr)
00314 {
00315 func (elem->data, userdata);
00316 elem = elem->next;
00317 }
00318 }
00319 }
00320
00321
00322 slist_iter
00323 slist_find (const slist * s, const void *data)
00324 {
00325 assert (s);
00326
00327
00328
00329
00330 return slist_find_if (s, data, _simple_compare);
00331 }
00332
00333
00334 slist_iter
00335 slist_find_if (const slist * s,
00336 const void *compare,
00337 int (*compare_func) (const void *data, const void *compare))
00338 {
00339 slist_iter i = slist_begin_iter (s);
00340 assert (s);
00341 assert (compare_func);
00342
00343 while (i.curr && !compare_func (i.curr->data, compare))
00344 slist_iter_and_next (&i);
00345
00346 return i;
00347 }
00348
00349
00350 int
00351 slist_iter_eq (slist_iter a, slist_iter b)
00352 {
00353 return a.curr == b.curr && a.prev == b.prev;
00354 }
00355
00356
00357 int
00358 slist_iter_at_end (slist_iter iter)
00359 {
00360 return iter.curr == 0;
00361 }
00362
00363
00364 unsigned int
00365 slist_length (const slist *s)
00366 {
00367 unsigned int length = 0;
00368 const slist_e *elem = s->head;
00369 assert (s);
00370
00371 while (elem)
00372 {
00373 ++length;
00374 elem = elem->next;
00375 }
00376
00377 return length;
00378 }
00379
00380
00381 #ifdef UNIT_TEST_SLIST_C
00382
00383 void *
00384 xmalloc (size_t size)
00385 {
00386 void *alloc = malloc (size);
00387
00388 if (alloc == 0)
00389 {
00390 printf ("out of memory (malloc)\n");
00391 exit (EXIT_FAILURE);
00392 }
00393
00394 return alloc;
00395 }
00396
00397 void
00398 multiply (void *value, void* result)
00399 {
00400 *(int*)result *= *(int*)value;
00401 }
00402
00403 int
00404 is_seven (const void *value, const void *compare)
00405 {
00406 return *(int*)value == 7;
00407 }
00408
00409 int
00410 main (int argc, char **argv)
00411 {
00412 slist list;
00413 int data[] = { 5, 6, 7, 8, 9, 10 };
00414 slist_iter i;
00415 slist_iter end;
00416 int result = 1;
00417
00418
00419 slist_init (&list);
00420 slist_append (&list, &data[1]);
00421
00422 if (slist_first (&list) != &data[1])
00423 {
00424 printf ("first slist_first() failed\n");
00425 exit (1);
00426 }
00427
00428 if (slist_last (&list) != &data[1])
00429 {
00430 printf ("first slist_last() failed\n");
00431 exit (1);
00432 }
00433
00434 slist_append (&list, &data[3]);
00435 slist_prepend (&list, &data[0]);
00436 if (slist_first (&list) != &data[0])
00437 {
00438 printf ("second slist_first() failed\n");
00439 exit (1);
00440 }
00441 if (slist_last (&list) != &data[3])
00442 {
00443 printf ("second slist_last() failed\n");
00444 exit (1);
00445 }
00446
00447 i = slist_begin_iter (&list);
00448 end = slist_end_iter (&list);
00449
00450 if (slist_at_iter (i) != &data[0])
00451 {
00452 printf ("first slist_at_iter() failed\n");
00453 exit (1);
00454 }
00455
00456 if (slist_iter_and_next (&i) != &data[0])
00457 {
00458 printf ("first slist_iter_and_next() failed\n");
00459 exit (1);
00460 }
00461
00462 if (slist_at_iter (i) != &data[1])
00463 {
00464 printf ("second slist_at_iter() failed\n");
00465 exit (1);
00466 }
00467
00468
00469 slist_iter_and_next (&i);
00470 slist_insert (&list, &i, &(data[2]));
00471
00472 if (i.prev->data != &(data[2]))
00473 {
00474 printf ("first slist_insert() failed\n");
00475 exit (1);
00476 }
00477
00478 slist_insert (&list, &end, &(data[4]));
00479
00480 if (slist_last (&list) != &(data[4]))
00481 {
00482 printf ("third slist_last() failed\n");
00483 exit (1);
00484 }
00485
00486
00487 if (slist_length (&list) != 5)
00488 {
00489 printf ("slist_length() failed (%i)\n", slist_length (&list));
00490 exit (1);
00491 }
00492
00493 slist_for_each (&list, multiply, &result);
00494 if (result != 15120)
00495 {
00496 printf ("slist_for_each() failed (%i)\n", result);
00497 exit (1);
00498 }
00499
00500 i = slist_find (&list, &(data[2]));
00501 if (slist_at_iter (i) != &(data[2]))
00502 {
00503 printf ("slist_find() failed\n");
00504 exit (1);
00505 }
00506
00507 result = 1;
00508 slist_for_each_range (i, end, multiply, &result);
00509 if (result != 504)
00510 {
00511 printf ("slist_for_each_range() failed (%i)\n", result);
00512 exit (1);
00513 }
00514
00515 i = slist_find (&list, &(data[5]));
00516 if (!slist_iter_eq (i, end))
00517 {
00518 printf ("slist_find() succeeded, but should have failed\n");
00519 exit (1);
00520 }
00521
00522 if (!slist_iter_at_end (i))
00523 {
00524 printf ("slist_iter_at_end() failed\n");
00525 exit (1);
00526 }
00527
00528 i = slist_find_if (&list, 0, is_seven );
00529 if (slist_at_iter (i) != &(data[2]))
00530 {
00531 printf ("slist_find_if() failed\n");
00532 exit (1);
00533 }
00534
00535 if ( slist_remove_first (&list) != &(data[0])
00536 || slist_first (&list) != &(data[1]))
00537 {
00538 printf ("slist_remove_first() failed\n");
00539 exit (1);
00540 }
00541
00542 if ( slist_remove_last (&list) != &(data[4])
00543 || slist_last (&list) != &(data[3]))
00544 {
00545 printf ("slist_remove_last() failed\n");
00546 exit (1);
00547 }
00548
00549 if (slist_remove_at_iter (&list, i) != &(data[2]))
00550 {
00551 printf ("slist_remove_iter() failed\n");
00552 exit (1);
00553 }
00554
00555 slist_delete_list_only (&list);
00556
00557 return 0;
00558 }
00559
00560 #endif