list.c revision 8b165ca7
1ea6ae205Smrg/* 2ea6ae205Smrg Copyright (c) 2002-2003 by Juliusz Chroboczek 3ea6ae205Smrg 4ea6ae205Smrg Permission is hereby granted, free of charge, to any person obtaining a copy 5ea6ae205Smrg of this software and associated documentation files (the "Software"), to deal 6ea6ae205Smrg in the Software without restriction, including without limitation the rights 7ea6ae205Smrg to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8ea6ae205Smrg copies of the Software, and to permit persons to whom the Software is 9ea6ae205Smrg furnished to do so, subject to the following conditions: 10ea6ae205Smrg 11ea6ae205Smrg The above copyright notice and this permission notice shall be included in 12ea6ae205Smrg all copies or substantial portions of the Software. 13ea6ae205Smrg 14ea6ae205Smrg THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15ea6ae205Smrg IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16ea6ae205Smrg FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17ea6ae205Smrg AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18ea6ae205Smrg LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19ea6ae205Smrg OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20ea6ae205Smrg THE SOFTWARE. 21ea6ae205Smrg*/ 22ea6ae205Smrg 238b165ca7Smrg#ifdef HAVE_CONFIG_H 2412458b28Smrg#include "config.h" 258b165ca7Smrg#endif 2612458b28Smrg 27ea6ae205Smrg#include <stdlib.h> 28ea6ae205Smrg#include <stdio.h> 29ea6ae205Smrg#include <stdarg.h> 30ea6ae205Smrg#include <string.h> 31ea6ae205Smrg#include "list.h" 32ea6ae205Smrg 33ea6ae205Smrgint 34663cdc11SmrglistMember(const char *elt, ListPtr list) 35ea6ae205Smrg{ 36ea6ae205Smrg while(list != NULL) { 37ea6ae205Smrg if(strcmp(elt, list->value) == 0) 38ea6ae205Smrg return 1; 39ea6ae205Smrg list = list->next; 40ea6ae205Smrg } 41ea6ae205Smrg return 0; 42ea6ae205Smrg} 43ea6ae205Smrg 44ea6ae205SmrgListPtr 45ea6ae205SmrglistCons(char *car, ListPtr cdr) 46ea6ae205Smrg{ 47ea6ae205Smrg ListPtr lcar = malloc(sizeof(ListRec)); 48ea6ae205Smrg if(!lcar) 49ea6ae205Smrg return NULL; 50ea6ae205Smrg lcar -> value = car; 51ea6ae205Smrg lcar -> next = cdr; 52ea6ae205Smrg return lcar; 53ea6ae205Smrg} 54ea6ae205Smrg 55ea6ae205SmrgListPtr 56ea6ae205SmrglistAdjoin(char *car, ListPtr cdr) 57ea6ae205Smrg{ 58ea6ae205Smrg if(listMember(car, cdr)) { 59ea6ae205Smrg free(car); 60ea6ae205Smrg return cdr; 61ea6ae205Smrg } 62ea6ae205Smrg return listCons(car, cdr); 63ea6ae205Smrg} 64ea6ae205Smrg 65ea6ae205Smrgchar * 66663cdc11Smrgdsprintf(const char *f, ...) 67ea6ae205Smrg{ 68ea6ae205Smrg va_list args; 69ea6ae205Smrg char *string; 7012458b28Smrg#ifdef HAVE_VASPRINTF 7112458b28Smrg va_start(args, f); 7212458b28Smrg if (vasprintf(&string, f, args) == -1) 7312458b28Smrg string = NULL; 7412458b28Smrg va_end(args); 7512458b28Smrg return string; 7612458b28Smrg#else 77ea6ae205Smrg { 78ea6ae205Smrg int n, size = 20; 79ea6ae205Smrg while(1) { 80ea6ae205Smrg if(size > 4096) 81ea6ae205Smrg return NULL; 82ea6ae205Smrg string = malloc(size); 83ea6ae205Smrg if(!string) 84ea6ae205Smrg return NULL; 85ea6ae205Smrg va_start(args, f); 86ea6ae205Smrg n = vsnprintf(string, size, f, args); 87ea6ae205Smrg va_end(args); 88ea6ae205Smrg if(n >= 0 && n < size) 89ea6ae205Smrg return string; 90ea6ae205Smrg else if(n >= size) 91ea6ae205Smrg size = n + 1; 92ea6ae205Smrg else 93ea6ae205Smrg size = size * 3 / 2 + 1; 94ea6ae205Smrg free(string); 95ea6ae205Smrg } 96ea6ae205Smrg } 9712458b28Smrg#endif 98ea6ae205Smrg} 99663cdc11Smrg 100ea6ae205Smrg 101ea6ae205SmrgListPtr 102663cdc11SmrglistConsF(ListPtr cdr, const char *f, ...) 103ea6ae205Smrg{ 104ea6ae205Smrg va_list args; 105ea6ae205Smrg char *string; 106ea6ae205Smrg { 107ea6ae205Smrg int n, size = 20; 108ea6ae205Smrg while(1) { 109ea6ae205Smrg if(size > 4096) 110ea6ae205Smrg return NULL; 111ea6ae205Smrg string = malloc(size); 112ea6ae205Smrg if(!string) 113ea6ae205Smrg return NULL; 114ea6ae205Smrg va_start(args, f); 115ea6ae205Smrg n = vsnprintf(string, size, f, args); 116ea6ae205Smrg va_end(args); 117ea6ae205Smrg if(n >= 0 && n < size) 118ea6ae205Smrg return listCons(string, cdr); 119ea6ae205Smrg else if(n >= size) 120ea6ae205Smrg size = n + 1; 121ea6ae205Smrg else 122ea6ae205Smrg size = size * 3 / 2 + 1; 123ea6ae205Smrg free(string); 124ea6ae205Smrg } 125ea6ae205Smrg } 126ea6ae205Smrg} 127ea6ae205Smrg 128ea6ae205SmrgListPtr 129663cdc11SmrglistAdjoinF(ListPtr cdr, const char *f, ...) 130ea6ae205Smrg{ 131ea6ae205Smrg va_list args; 132ea6ae205Smrg char *string; 133ea6ae205Smrg { 134ea6ae205Smrg int n, size = 20; 135ea6ae205Smrg while(1) { 136ea6ae205Smrg if(size > 4096) 137ea6ae205Smrg return NULL; 138ea6ae205Smrg string = malloc(size); 139ea6ae205Smrg if(!string) 140ea6ae205Smrg return NULL; 141ea6ae205Smrg va_start(args, f); 142ea6ae205Smrg n = vsnprintf(string, size, f, args); 143ea6ae205Smrg va_end(args); 144ea6ae205Smrg if(n >= 0 && n < size) 145ea6ae205Smrg return listAdjoin(string, cdr); 146ea6ae205Smrg else if(n >= size) 147ea6ae205Smrg size = n + 1; 148ea6ae205Smrg else 149ea6ae205Smrg size = size * 3 / 2 + 1; 150ea6ae205Smrg free(string); 151ea6ae205Smrg } 152ea6ae205Smrg } 153ea6ae205Smrg} 154ea6ae205Smrg 155ea6ae205Smrgint 156ea6ae205SmrglistLength(ListPtr list) 157ea6ae205Smrg{ 158ea6ae205Smrg int n = 0; 159ea6ae205Smrg while(list) { 160ea6ae205Smrg n++; 161ea6ae205Smrg list = list->next; 162ea6ae205Smrg } 163ea6ae205Smrg return n; 164ea6ae205Smrg} 165ea6ae205Smrg 166663cdc11SmrgListPtr 167ea6ae205SmrgappendList(ListPtr first, ListPtr second) 168ea6ae205Smrg{ 169ea6ae205Smrg ListPtr current; 170ea6ae205Smrg 171ea6ae205Smrg if(second == NULL) 172ea6ae205Smrg return first; 173ea6ae205Smrg 174ea6ae205Smrg if(first == NULL) 175ea6ae205Smrg return second; 176ea6ae205Smrg 177ea6ae205Smrg for(current = first; current->next; current = current->next) 178ea6ae205Smrg ; 179ea6ae205Smrg 180ea6ae205Smrg current->next = second; 181ea6ae205Smrg return first; 182ea6ae205Smrg} 183ea6ae205Smrg 184ea6ae205SmrgListPtr 185ea6ae205SmrgmakeList(char **a, int n, ListPtr old, int begin) 186ea6ae205Smrg{ 187ea6ae205Smrg ListPtr first, current, next; 188ea6ae205Smrg int i; 189ea6ae205Smrg 190ea6ae205Smrg if(n == 0) 191ea6ae205Smrg return old; 192ea6ae205Smrg 193ea6ae205Smrg first = malloc(sizeof(ListRec)); 194ea6ae205Smrg if(!first) 195ea6ae205Smrg return NULL; 196ea6ae205Smrg 197ea6ae205Smrg first->value = a[0]; 198ea6ae205Smrg first->next = NULL; 199ea6ae205Smrg 200ea6ae205Smrg current = first; 201ea6ae205Smrg for(i = 1; i < n; i++) { 202ea6ae205Smrg next = malloc(sizeof(ListRec)); 203245f6787Smrg if(!next) { 204245f6787Smrg destroyList(first); 205ea6ae205Smrg return NULL; 206245f6787Smrg } 207ea6ae205Smrg next->value = a[i]; 208ea6ae205Smrg next->next = NULL; 209ea6ae205Smrg 210ea6ae205Smrg current->next = next; 211ea6ae205Smrg current = next; 212ea6ae205Smrg } 213ea6ae205Smrg if(begin) { 214ea6ae205Smrg current->next = old; 215ea6ae205Smrg return first; 216ea6ae205Smrg } else { 217ea6ae205Smrg return appendList(old, first); 218ea6ae205Smrg } 219ea6ae205Smrg} 220ea6ae205Smrg 221ea6ae205SmrgListPtr 222ea6ae205SmrgreverseList(ListPtr old) 223ea6ae205Smrg{ 224ea6ae205Smrg ListPtr new = NULL, current; 225ea6ae205Smrg while(old) { 226ea6ae205Smrg current = old; 227ea6ae205Smrg old = old->next; 228ea6ae205Smrg current->next = new; 229ea6ae205Smrg new = current; 230ea6ae205Smrg } 231ea6ae205Smrg return new; 232ea6ae205Smrg} 233ea6ae205Smrg 234245f6787Smrg/* qsort helper for sorting list entries */ 235245f6787Smrgstatic int 236245f6787SmrgcompareListEntries(const void *a, const void *b) 237245f6787Smrg{ 238245f6787Smrg const ListPtr lista = *(const ListPtr *) a; 239245f6787Smrg const ListPtr listb = *(const ListPtr *) b; 240245f6787Smrg 241245f6787Smrg return strcmp(lista->value, listb->value); 242245f6787Smrg} 243245f6787Smrg 244245f6787SmrgListPtr 245245f6787SmrgsortList(ListPtr old) 246245f6787Smrg{ 247245f6787Smrg int i; 248245f6787Smrg int l = listLength(old); 249245f6787Smrg ListPtr n; 25048f45e26Smrg ListPtr *sorted; 25148f45e26Smrg 25248f45e26Smrg if (l <= 0) 25348f45e26Smrg return old; 25448f45e26Smrg 25548f45e26Smrg sorted = malloc(l * sizeof(ListPtr)); 256245f6787Smrg 257245f6787Smrg if (sorted == NULL) 258245f6787Smrg return old; 259245f6787Smrg 260245f6787Smrg for (n = old, i = 0; n != NULL; n = n->next) { 261245f6787Smrg sorted[i++] = n; 262245f6787Smrg } 263245f6787Smrg qsort(sorted, i, sizeof(ListPtr), compareListEntries); 264245f6787Smrg n = sorted[0]; 265245f6787Smrg for (i = 0; i < (l - 1); i++) { 266245f6787Smrg sorted[i]->next = sorted[i+1]; 267245f6787Smrg } 268245f6787Smrg sorted[i]->next = NULL; 269245f6787Smrg free(sorted); 270245f6787Smrg return n; 271245f6787Smrg} 272245f6787Smrg 273ea6ae205Smrgvoid 274ea6ae205SmrgdestroyList(ListPtr old) 275ea6ae205Smrg{ 276ea6ae205Smrg ListPtr next; 277ea6ae205Smrg if(!old) 278ea6ae205Smrg return; 279ea6ae205Smrg while(old) { 280ea6ae205Smrg next = old->next; 281ea6ae205Smrg free(old); 282ea6ae205Smrg old = next; 283ea6ae205Smrg } 284ea6ae205Smrg} 285ea6ae205Smrg 286ea6ae205Smrgvoid 287ea6ae205SmrgdeepDestroyList(ListPtr old) 288ea6ae205Smrg{ 289ea6ae205Smrg ListPtr next; 290ea6ae205Smrg if(!old) 291ea6ae205Smrg return; 292ea6ae205Smrg while(old) { 293ea6ae205Smrg next = old->next; 294ea6ae205Smrg free(old->value); 295ea6ae205Smrg free(old); 296ea6ae205Smrg old = next; 297ea6ae205Smrg } 298ea6ae205Smrg} 299