list.c

Go to the documentation of this file.
00001 /*  Copyright (c) 2006-2007, Philip Busch <broesel@studcs.uni-sb.de>
00002  *  All rights reserved.
00003  *
00004  *  Redistribution and use in source and binary forms, with or without
00005  *  modification, are permitted provided that the following conditions are met:
00006  *
00007  *   - Redistributions of source code must retain the above copyright notice,
00008  *     this list of conditions and the following disclaimer.
00009  *   - Redistributions in binary form must reproduce the above copyright
00010  *     notice, this list of conditions and the following disclaimer in the
00011  *     documentation and/or other materials provided with the distribution.
00012  *
00013  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00014  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00015  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00016  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00017  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00018  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00019  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00020  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00021  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00022  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00023  *  POSSIBILITY OF SUCH DAMAGE.
00024  */
00025 
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <assert.h>
00029 #include <string.h>
00030 #include "list.h"
00031 
00032 
00053 int list_push(node_l **_x, void *_data)
00054 {
00055         node_l *n = NULL;
00056 
00057         assert(_x != NULL);
00058 
00059         if((n = (node_l *)malloc(sizeof(node_l))) == NULL) {
00060                 return(-1);
00061         } else {
00062                 n->data = _data;
00063                 n->next = *_x;
00064 
00065                 *_x = n;
00066                 return(0);
00067         }
00068 }
00069 
00080 void *list_pop(node_l **_x)
00081 {
00082         node_l *n = NULL;
00083         void *data;
00084         
00085         assert(_x != NULL);
00086 
00087         if(*_x == NULL)
00088                 return(NULL);
00089                 
00090         n = *_x;
00091         *_x  = n->next;
00092         data = n->data;
00093         free(n);
00094 
00095         return(data);
00096 }
00097 
00109 int list_move(node_l **_dest, node_l **_src)
00110 {
00111         node_l *n = NULL;
00112         
00113         assert((_dest != NULL) && (_src != NULL));
00114 
00115         if(*_src == NULL)
00116                 return(-1);
00117 
00118         n = *_src;
00119         *_src = n->next;
00120         n->next = *_dest;
00121         *_dest = n;
00122 
00123         return(0);
00124 }
00125 
00136 int list_reverse(node_l **_x)
00137 {
00138         node_l *n = NULL;
00139 
00140         assert(_x != NULL);
00141 
00142         while(list_move(&n, _x) >= 0);
00143         *_x = n;
00144 
00145         return(0);
00146 }
00147 
00157 node_l *list_sub(const node_l *_x, int _pos)
00158 {
00159         int i = 0;
00160         node_l *n = (node_l *)_x;
00161 
00162         assert(_x != NULL);
00163 
00164         if(_pos < 0)
00165                 return(NULL);
00166 
00167         while(i++ < _pos) {
00168                 if((n = n->next) == NULL)
00169                         return(NULL);
00170         }
00171 
00172         return(n);
00173 }
00174 
00186 int list_insert(node_l **_x, int _pos, void *_data)
00187 {
00188         node_l *p;
00189 
00190         assert(_x != NULL);
00191 
00192         if(_pos < 0)
00193                 return(-1);
00194                 
00195         if(_pos == 0)
00196                 return(list_push(_x, _data));
00197 
00198         if((p = list_sub(*_x, _pos-1)) == NULL)
00199                 return(-1);
00200 
00201         return(list_push(&(p->next), _data));
00202 }
00203 
00214 void *list_remove(node_l **_x, int _pos)
00215 {
00216         node_l *current = *_x;
00217         node_l *next = NULL;
00218         void *data;
00219 
00220         assert(_x != NULL);
00221 
00222         if(_pos < 0)
00223                 return(NULL);
00224         
00225         if(*_x == NULL)
00226                 return(NULL);
00227 
00228         if(_pos == 0)
00229                 return(list_pop(_x));
00230 
00231         while(--_pos) {
00232                 current = current->next;
00233         }
00234 
00235         if((next = current->next) == NULL)
00236                 return(NULL);
00237                 
00238         data = next->data;
00239         current->next = next->next;
00240 
00241         free(next);
00242         return(data);
00243 }
00244 
00255 void *list_get(const node_l *_x, int _pos)
00256 {
00257         int i = 0;
00258 
00259         if(_pos < 0)
00260                 return(NULL);
00261 
00262         while(_x != NULL) {
00263                 if(_pos == i++)
00264                         return(_x->data);
00265                 _x = _x->next;
00266         }
00267 
00268         return(NULL);
00269 }
00270 
00279 size_t list_size(const node_l *_x)
00280 {
00281         size_t s = 0;
00282 
00283         for(; _x != NULL; s++, _x = _x->next);
00284         return(s);
00285 }
00286 
00297 node_l *list_join(node_l *_dest, node_l *_src)
00298 {
00299         node_l *n = _dest;
00300 
00301         if(_dest == NULL)
00302                 return(_src);
00303 
00304         if(_src == NULL)
00305                 return(_dest);
00306 
00307         while(_dest->next != NULL)
00308                 _dest = _dest->next;
00309                 
00310         _dest->next = _src;
00311 
00312         return(n);
00313 }
00314 
00324 void list_print(const node_l *_a)
00325 {
00326         data *foo;
00327         int i = 0;
00328 
00329         while(_a != NULL) {
00330                 foo = (data *)_a->data;
00331                 printf("%03d: %3d - %s\n", i++, foo->n, foo->str);
00332                 _a = _a->next;
00333         }
00334 }
00335 
00350 /* hare and tortoise approach / classic Floyd’s Cycle Finding Algorithm */
00351 int list_split(node_l **_src, node_l **_front, node_l **_back)
00352 {
00353         node_l *fast, *slow;
00354 
00355         assert((_src != NULL) && (_front != NULL) && (_back != NULL));
00356 
00357         if((*_src == NULL) || ((*_src)->next == NULL)) {
00358                 *_back = NULL;
00359         } else {
00360                 slow = *_src;
00361                 fast = slow->next;
00362                 
00363                 while(fast != NULL) {
00364                         fast = fast->next;
00365                         if(fast != NULL) {
00366                                 slow = slow->next;
00367                                 fast = fast->next;
00368                         }
00369                 }
00370                 *_back = slow->next;
00371                 slow->next = NULL;
00372         }
00373 
00374         *_front = *_src;
00375         *_src = NULL;
00376         return(0);
00377 }
00378 
00396 int list_merge(node_l **_dest, node_l **_a, node_l **_b, int _cmp(void *, void *))
00397 {
00398         node_l *ret = NULL;
00399         node_l **last = &ret;
00400 
00401         assert((_dest != NULL) && (_a != NULL) && (_b != NULL));
00402 
00403         for(;;) {
00404                 if(*_a == NULL) {
00405                         *last = *_b;
00406                         break;
00407                 }
00408 
00409                 if(*_b == NULL) {
00410                         *last = *_a;
00411                         break;
00412                 }
00413                 
00414                 if(_cmp((*_a)->data, (*_b)->data) <= 0) {
00415                         list_move(last, _a);
00416                 } else {
00417                         list_move(last, _b);
00418                 }
00419                 
00420                 last = &((*last)->next);
00421         }
00422 
00423         *_dest = ret;
00424         return(0);
00425 }
00426 
00438 int list_sort(node_l **_x, int _cmp(void *, void *))
00439 {
00440         node_l *l, *r;
00441 
00442         assert(_x != NULL);
00443 
00444         if(*_x == NULL || (*_x)->next == NULL)
00445                 return(0);
00446 
00447         list_split(_x, &l, &r);
00448 
00449         list_sort(&l, _cmp);
00450         list_sort(&r, _cmp);
00451         
00452         list_merge(_x, &l, &r, _cmp);
00453 
00454         return(0);
00455 }
00456 
00473 int list_copy(const node_l *_src, node_l **_dest)
00474 {
00475         assert(_src != NULL);
00476 
00477         *_dest = NULL;
00478 
00479         while(_src) {
00480                 if(list_push(_dest, _src->data)) {
00481                         return(-1);
00482                 } else {
00483                         _src = _src->next;
00484                 }
00485         }
00486         return(list_reverse(_dest));
00487 }
00488 
00500 int list_realloc(node_l *_x, size_t _sz)
00501 {
00502         void *data;
00503 
00504         assert(_x != NULL);
00505 
00506         while(_x) {
00507                 if((data = malloc(_sz)) == NULL) {
00508                         return(-1);
00509                 } else {
00510                         _x->data = memcpy(data, _x->data, _sz);
00511                         _x = _x->next;
00512                 }
00513         }
00514         return(0);
00515 }
00516 
00529 int list_dup(node_l *_src, node_l **_dest, size_t _sz)
00530 {
00531         assert(_src != NULL);
00532 
00533         if(list_copy(_src, _dest) < 0)
00534                 return(-1);
00535 
00536         if(list_realloc(*_dest, _sz) < 0)
00537                 return(-1);
00538                 
00539         return(0);
00540 }
00541 
00552 void list_delete(node_l **_x)
00553 {
00554         assert(_x != NULL);
00555         
00556         while(*_x) {
00557                 list_pop(_x);
00558         }
00559 }
00560 
00571 void list_destroy(node_l **_x)
00572 {
00573         assert(_x != NULL);
00574 
00575         while(*_x) {
00576                 free(list_pop(_x));
00577         }
00578 }
00579 
00588 /* auxiliary function to create a short list */
00589 node_l *list_create123()
00590 {
00591         node_l *n = NULL;
00592         data *a=malloc(sizeof(data)),
00593              *b=malloc(sizeof(data)),
00594              *c=malloc(sizeof(data));
00595 
00596         a->n = 1;
00597         strcpy(a->str, "foo");
00598         b->n = 2;
00599         strcpy(b->str, "bar");
00600         c->n = 3;
00601         strcpy(c->str, "snafu");
00602 
00603         list_push(&n, a);
00604         list_push(&n, b);
00605         list_push(&n, c);
00606         return(n);
00607 }
00608 
00619 /* auxiliary function for testing list_sort() */
00620 int cmp(void *_a, void *_b)
00621 {
00622         data *a = (data *)_a, *b = (data *)_b;
00623 
00624         if(a->n < b->n) return(-1);
00625         if(a->n > b->n) return(1);
00626         return(0);
00627 }
00628 
00643 int list_foreach(node_l *_x, int _func(void *))
00644 {
00645         int ret = 0;
00646 
00647         while(_x) {
00648                 ret *= _func(_x->data);
00649                 _x = _x->next;
00650         }
00651                 
00652         return(ret);
00653 }
00654 

Generated on Thu Jul 19 13:36:09 2007 for libv by  doxygen 1.5.1-p1. Thank you, SourceForge.net Logo