Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

slist.c

00001 /*  slist.c - Single linked list.
00002  *            This file is part of the FreeLCD package.
00003  *
00004  *  $Id: slist_8c-source.html,v 1.1 2003/02/16 22:50:41 unicorn Exp $
00005  *
00006  *  This program is free software; you can redistribute it and/or modify it
00007  *  under the terms of the GNU General Public License as published by the
00008  *  Free Software Foundation; either version 2 of the License, or (at your
00009  *  option) any later version.
00010  * 
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00019  *  MA  02111-1307  USA
00020  *
00021  *  Copyright (c) 2002, 2003, Jeroen van den Berg <unicorn@hippie.nu>
00022  */
00023 
00024 #include <stdlib.h>
00025 #include <assert.h>
00026 
00027 #include "slist.h"
00028 #include "xmalloc.h"
00029 
00030 /*---------------------------------------------------------------- _nop --*/
00031 static void
00032 _nop (void *data)
00033 {
00034   /* Do nothing */
00035 }
00036 
00037 /*----------------------------------------------------- _simple_compare --*/
00038 static inline int
00039 _simple_compare (const void *data, const void *compare)
00040 {
00041   return data == compare;
00042 }
00043 
00044 /*---------------------------------------------------------- slist_init --*/
00045 void
00046 slist_init (slist * s)
00047 {
00048   assert (s);
00049   s->head = 0;
00050   s->tail = 0;
00051 }
00052 
00053 /*------------------------------------------------ slist_delete_special --*/
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 /*-------------------------------------------------------- slist_delete --*/
00070 void
00071 slist_delete (slist * s)
00072 {
00073   assert (s);
00074   slist_delete_special (s, free);
00075 }
00076 
00077 /*---------------------------------------------- slist_delete_list_only --*/
00078 void
00079 slist_delete_list_only (slist * s)
00080 {
00081   assert (s);
00082   slist_delete_special (s, _nop);
00083 }
00084 
00085 /*--------------------------------------------------------- slist_first --*/
00086 void *
00087 slist_first (const slist * s)
00088 {
00089   assert (s);
00090   return s->head ? s->head->data : 0;
00091 }
00092 
00093 /*---------------------------------------------------------- slist_last --*/
00094 void *
00095 slist_last (const slist * s)
00096 {
00097   assert (s);
00098   return s->tail ? s->tail->data : 0;
00099 }
00100 
00101 /*------------------------------------------------------- slist_at_iter --*/
00102 void *
00103 slist_at_iter (slist_iter iter)
00104 {
00105   return iter.curr ? iter.curr->data : 0;
00106 }
00107 
00108 /*------------------------------------------------------- slist_prepend --*/
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 /*-------------------------------------------------------- slist_append --*/
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 /*-------------------------------------------------------- slist_insert --*/
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 /*-------------------------------------------------- slist_remove_first --*/
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 /*--------------------------------------------------- slist_remove_last --*/
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 /*--------------------------------------------------- slist_remove_iter --*/
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 /*---------------------------------------------------- slist_begin_iter --*/
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 /*------------------------------------------------------ slist_end_iter --*/
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 /*------------------------------------------------- slist_iter_and_next --*/
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 /*------------------------------------------------------ slist_for_each --*/
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 /*------------------------------------------------ slist_for_each_range --*/
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 /*---------------------------------------------------------- slist_find --*/
00322 slist_iter
00323 slist_find (const slist * s, const void *data)
00324 {
00325   assert (s);
00326 
00327   /*  The _simple_compare() function is defined near the top, and only
00328    *  compares the two given pointers.
00329    */
00330   return slist_find_if (s, data, _simple_compare);
00331 }
00332 
00333 /*------------------------------------------------------- slist_find_if --*/
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 /*------------------------------------------------------- slist_iter_eq --*/
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 /*--------------------------------------------------- slist_iter_at_end --*/
00357 int
00358 slist_iter_at_end (slist_iter iter)
00359 {
00360   return iter.curr == 0;
00361 }
00362 
00363 /*-------------------------------------------------------- slist_length --*/
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

Generated on Sun Feb 16 23:39:49 2003 for FreeLCD by doxygen1.2.18