list.c revision 12458b28
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 2312458b28Smrg#include "config.h" 2412458b28Smrg 25ea6ae205Smrg#include <stdlib.h> 26ea6ae205Smrg#include <stdio.h> 27ea6ae205Smrg#include <stdarg.h> 28ea6ae205Smrg#include <string.h> 29ea6ae205Smrg#include "list.h" 30ea6ae205Smrg 31ea6ae205Smrgint 32663cdc11SmrglistMember(const char *elt, ListPtr list) 33ea6ae205Smrg{ 34ea6ae205Smrg while(list != NULL) { 35ea6ae205Smrg if(strcmp(elt, list->value) == 0) 36ea6ae205Smrg return 1; 37ea6ae205Smrg list = list->next; 38ea6ae205Smrg } 39ea6ae205Smrg return 0; 40ea6ae205Smrg} 41ea6ae205Smrg 42ea6ae205SmrgListPtr 43ea6ae205SmrglistCons(char *car, ListPtr cdr) 44ea6ae205Smrg{ 45ea6ae205Smrg ListPtr lcar = malloc(sizeof(ListRec)); 46ea6ae205Smrg if(!lcar) 47ea6ae205Smrg return NULL; 48ea6ae205Smrg lcar -> value = car; 49ea6ae205Smrg lcar -> next = cdr; 50ea6ae205Smrg return lcar; 51ea6ae205Smrg} 52ea6ae205Smrg 53ea6ae205SmrgListPtr 54ea6ae205SmrglistAdjoin(char *car, ListPtr cdr) 55ea6ae205Smrg{ 56ea6ae205Smrg if(listMember(car, cdr)) { 57ea6ae205Smrg free(car); 58ea6ae205Smrg return cdr; 59ea6ae205Smrg } 60ea6ae205Smrg return listCons(car, cdr); 61ea6ae205Smrg} 62ea6ae205Smrg 63ea6ae205Smrgchar * 64663cdc11Smrgdsprintf(const char *f, ...) 65ea6ae205Smrg{ 66ea6ae205Smrg va_list args; 67ea6ae205Smrg char *string; 6812458b28Smrg#ifdef HAVE_VASPRINTF 6912458b28Smrg va_start(args, f); 7012458b28Smrg if (vasprintf(&string, f, args) == -1) 7112458b28Smrg string = NULL; 7212458b28Smrg va_end(args); 7312458b28Smrg return string; 7412458b28Smrg#else 75ea6ae205Smrg { 76ea6ae205Smrg int n, size = 20; 77ea6ae205Smrg while(1) { 78ea6ae205Smrg if(size > 4096) 79ea6ae205Smrg return NULL; 80ea6ae205Smrg string = malloc(size); 81ea6ae205Smrg if(!string) 82ea6ae205Smrg return NULL; 83ea6ae205Smrg va_start(args, f); 84ea6ae205Smrg n = vsnprintf(string, size, f, args); 85ea6ae205Smrg va_end(args); 86ea6ae205Smrg if(n >= 0 && n < size) 87ea6ae205Smrg return string; 88ea6ae205Smrg else if(n >= size) 89ea6ae205Smrg size = n + 1; 90ea6ae205Smrg else 91ea6ae205Smrg size = size * 3 / 2 + 1; 92ea6ae205Smrg free(string); 93ea6ae205Smrg } 94ea6ae205Smrg } 9512458b28Smrg#endif 96ea6ae205Smrg} 97663cdc11Smrg 98ea6ae205Smrg 99ea6ae205SmrgListPtr 100663cdc11SmrglistConsF(ListPtr cdr, const char *f, ...) 101ea6ae205Smrg{ 102ea6ae205Smrg va_list args; 103ea6ae205Smrg char *string; 104ea6ae205Smrg { 105ea6ae205Smrg int n, size = 20; 106ea6ae205Smrg while(1) { 107ea6ae205Smrg if(size > 4096) 108ea6ae205Smrg return NULL; 109ea6ae205Smrg string = malloc(size); 110ea6ae205Smrg if(!string) 111ea6ae205Smrg return NULL; 112ea6ae205Smrg va_start(args, f); 113ea6ae205Smrg n = vsnprintf(string, size, f, args); 114ea6ae205Smrg va_end(args); 115ea6ae205Smrg if(n >= 0 && n < size) 116ea6ae205Smrg return listCons(string, cdr); 117ea6ae205Smrg else if(n >= size) 118ea6ae205Smrg size = n + 1; 119ea6ae205Smrg else 120ea6ae205Smrg size = size * 3 / 2 + 1; 121ea6ae205Smrg free(string); 122ea6ae205Smrg } 123ea6ae205Smrg } 124ea6ae205Smrg} 125ea6ae205Smrg 126ea6ae205SmrgListPtr 127663cdc11SmrglistAdjoinF(ListPtr cdr, const char *f, ...) 128ea6ae205Smrg{ 129ea6ae205Smrg va_list args; 130ea6ae205Smrg char *string; 131ea6ae205Smrg { 132ea6ae205Smrg int n, size = 20; 133ea6ae205Smrg while(1) { 134ea6ae205Smrg if(size > 4096) 135ea6ae205Smrg return NULL; 136ea6ae205Smrg string = malloc(size); 137ea6ae205Smrg if(!string) 138ea6ae205Smrg return NULL; 139ea6ae205Smrg va_start(args, f); 140ea6ae205Smrg n = vsnprintf(string, size, f, args); 141ea6ae205Smrg va_end(args); 142ea6ae205Smrg if(n >= 0 && n < size) 143ea6ae205Smrg return listAdjoin(string, cdr); 144ea6ae205Smrg else if(n >= size) 145ea6ae205Smrg size = n + 1; 146ea6ae205Smrg else 147ea6ae205Smrg size = size * 3 / 2 + 1; 148ea6ae205Smrg free(string); 149ea6ae205Smrg } 150ea6ae205Smrg } 151ea6ae205Smrg} 152ea6ae205Smrg 153ea6ae205Smrgint 154ea6ae205SmrglistLength(ListPtr list) 155ea6ae205Smrg{ 156ea6ae205Smrg int n = 0; 157ea6ae205Smrg while(list) { 158ea6ae205Smrg n++; 159ea6ae205Smrg list = list->next; 160ea6ae205Smrg } 161ea6ae205Smrg return n; 162ea6ae205Smrg} 163ea6ae205Smrg 164663cdc11SmrgListPtr 165ea6ae205SmrgappendList(ListPtr first, ListPtr second) 166ea6ae205Smrg{ 167ea6ae205Smrg ListPtr current; 168ea6ae205Smrg 169ea6ae205Smrg if(second == NULL) 170ea6ae205Smrg return first; 171ea6ae205Smrg 172ea6ae205Smrg if(first == NULL) 173ea6ae205Smrg return second; 174ea6ae205Smrg 175ea6ae205Smrg for(current = first; current->next; current = current->next) 176ea6ae205Smrg ; 177ea6ae205Smrg 178ea6ae205Smrg current->next = second; 179ea6ae205Smrg return first; 180ea6ae205Smrg} 181ea6ae205Smrg 182ea6ae205SmrgListPtr 183ea6ae205SmrgmakeList(char **a, int n, ListPtr old, int begin) 184ea6ae205Smrg{ 185ea6ae205Smrg ListPtr first, current, next; 186ea6ae205Smrg int i; 187ea6ae205Smrg 188ea6ae205Smrg if(n == 0) 189ea6ae205Smrg return old; 190ea6ae205Smrg 191ea6ae205Smrg first = malloc(sizeof(ListRec)); 192ea6ae205Smrg if(!first) 193ea6ae205Smrg return NULL; 194ea6ae205Smrg 195ea6ae205Smrg first->value = a[0]; 196ea6ae205Smrg first->next = NULL; 197ea6ae205Smrg 198ea6ae205Smrg current = first; 199ea6ae205Smrg for(i = 1; i < n; i++) { 200ea6ae205Smrg next = malloc(sizeof(ListRec)); 201245f6787Smrg if(!next) { 202245f6787Smrg destroyList(first); 203ea6ae205Smrg return NULL; 204245f6787Smrg } 205ea6ae205Smrg next->value = a[i]; 206ea6ae205Smrg next->next = NULL; 207ea6ae205Smrg 208ea6ae205Smrg current->next = next; 209ea6ae205Smrg current = next; 210ea6ae205Smrg } 211ea6ae205Smrg if(begin) { 212ea6ae205Smrg current->next = old; 213ea6ae205Smrg return first; 214ea6ae205Smrg } else { 215ea6ae205Smrg return appendList(old, first); 216ea6ae205Smrg } 217ea6ae205Smrg} 218ea6ae205Smrg 219ea6ae205SmrgListPtr 220ea6ae205SmrgreverseList(ListPtr old) 221ea6ae205Smrg{ 222ea6ae205Smrg ListPtr new = NULL, current; 223ea6ae205Smrg while(old) { 224ea6ae205Smrg current = old; 225ea6ae205Smrg old = old->next; 226ea6ae205Smrg current->next = new; 227ea6ae205Smrg new = current; 228ea6ae205Smrg } 229ea6ae205Smrg return new; 230ea6ae205Smrg} 231ea6ae205Smrg 232245f6787Smrg/* qsort helper for sorting list entries */ 233245f6787Smrgstatic int 234245f6787SmrgcompareListEntries(const void *a, const void *b) 235245f6787Smrg{ 236245f6787Smrg const ListPtr lista = *(const ListPtr *) a; 237245f6787Smrg const ListPtr listb = *(const ListPtr *) b; 238245f6787Smrg 239245f6787Smrg return strcmp(lista->value, listb->value); 240245f6787Smrg} 241245f6787Smrg 242245f6787SmrgListPtr 243245f6787SmrgsortList(ListPtr old) 244245f6787Smrg{ 245245f6787Smrg int i; 246245f6787Smrg int l = listLength(old); 247245f6787Smrg ListPtr n; 24848f45e26Smrg ListPtr *sorted; 24948f45e26Smrg 25048f45e26Smrg if (l <= 0) 25148f45e26Smrg return old; 25248f45e26Smrg 25348f45e26Smrg sorted = malloc(l * sizeof(ListPtr)); 254245f6787Smrg 255245f6787Smrg if (sorted == NULL) 256245f6787Smrg return old; 257245f6787Smrg 258245f6787Smrg for (n = old, i = 0; n != NULL; n = n->next) { 259245f6787Smrg sorted[i++] = n; 260245f6787Smrg } 261245f6787Smrg qsort(sorted, i, sizeof(ListPtr), compareListEntries); 262245f6787Smrg n = sorted[0]; 263245f6787Smrg for (i = 0; i < (l - 1); i++) { 264245f6787Smrg sorted[i]->next = sorted[i+1]; 265245f6787Smrg } 266245f6787Smrg sorted[i]->next = NULL; 267245f6787Smrg free(sorted); 268245f6787Smrg return n; 269245f6787Smrg} 270245f6787Smrg 271ea6ae205Smrgvoid 272ea6ae205SmrgdestroyList(ListPtr old) 273ea6ae205Smrg{ 274ea6ae205Smrg ListPtr next; 275ea6ae205Smrg if(!old) 276ea6ae205Smrg return; 277ea6ae205Smrg while(old) { 278ea6ae205Smrg next = old->next; 279ea6ae205Smrg free(old); 280ea6ae205Smrg old = next; 281ea6ae205Smrg } 282ea6ae205Smrg} 283ea6ae205Smrg 284ea6ae205Smrgvoid 285ea6ae205SmrgdeepDestroyList(ListPtr old) 286ea6ae205Smrg{ 287ea6ae205Smrg ListPtr next; 288ea6ae205Smrg if(!old) 289ea6ae205Smrg return; 290ea6ae205Smrg while(old) { 291ea6ae205Smrg next = old->next; 292ea6ae205Smrg free(old->value); 293ea6ae205Smrg free(old); 294ea6ae205Smrg old = next; 295ea6ae205Smrg } 296ea6ae205Smrg} 297