list.c revision 12458b28
1/* 2 Copyright (c) 2002-2003 by Juliusz Chroboczek 3 4 Permission is hereby granted, free of charge, to any person obtaining a copy 5 of this software and associated documentation files (the "Software"), to deal 6 in the Software without restriction, including without limitation the rights 7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 copies of the Software, and to permit persons to whom the Software is 9 furnished to do so, subject to the following conditions: 10 11 The above copyright notice and this permission notice shall be included in 12 all copies or substantial portions of the Software. 13 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 THE SOFTWARE. 21*/ 22 23#include "config.h" 24 25#include <stdlib.h> 26#include <stdio.h> 27#include <stdarg.h> 28#include <string.h> 29#include "list.h" 30 31int 32listMember(const char *elt, ListPtr list) 33{ 34 while(list != NULL) { 35 if(strcmp(elt, list->value) == 0) 36 return 1; 37 list = list->next; 38 } 39 return 0; 40} 41 42ListPtr 43listCons(char *car, ListPtr cdr) 44{ 45 ListPtr lcar = malloc(sizeof(ListRec)); 46 if(!lcar) 47 return NULL; 48 lcar -> value = car; 49 lcar -> next = cdr; 50 return lcar; 51} 52 53ListPtr 54listAdjoin(char *car, ListPtr cdr) 55{ 56 if(listMember(car, cdr)) { 57 free(car); 58 return cdr; 59 } 60 return listCons(car, cdr); 61} 62 63char * 64dsprintf(const char *f, ...) 65{ 66 va_list args; 67 char *string; 68#ifdef HAVE_VASPRINTF 69 va_start(args, f); 70 if (vasprintf(&string, f, args) == -1) 71 string = NULL; 72 va_end(args); 73 return string; 74#else 75 { 76 int n, size = 20; 77 while(1) { 78 if(size > 4096) 79 return NULL; 80 string = malloc(size); 81 if(!string) 82 return NULL; 83 va_start(args, f); 84 n = vsnprintf(string, size, f, args); 85 va_end(args); 86 if(n >= 0 && n < size) 87 return string; 88 else if(n >= size) 89 size = n + 1; 90 else 91 size = size * 3 / 2 + 1; 92 free(string); 93 } 94 } 95#endif 96} 97 98 99ListPtr 100listConsF(ListPtr cdr, const char *f, ...) 101{ 102 va_list args; 103 char *string; 104 { 105 int n, size = 20; 106 while(1) { 107 if(size > 4096) 108 return NULL; 109 string = malloc(size); 110 if(!string) 111 return NULL; 112 va_start(args, f); 113 n = vsnprintf(string, size, f, args); 114 va_end(args); 115 if(n >= 0 && n < size) 116 return listCons(string, cdr); 117 else if(n >= size) 118 size = n + 1; 119 else 120 size = size * 3 / 2 + 1; 121 free(string); 122 } 123 } 124} 125 126ListPtr 127listAdjoinF(ListPtr cdr, const char *f, ...) 128{ 129 va_list args; 130 char *string; 131 { 132 int n, size = 20; 133 while(1) { 134 if(size > 4096) 135 return NULL; 136 string = malloc(size); 137 if(!string) 138 return NULL; 139 va_start(args, f); 140 n = vsnprintf(string, size, f, args); 141 va_end(args); 142 if(n >= 0 && n < size) 143 return listAdjoin(string, cdr); 144 else if(n >= size) 145 size = n + 1; 146 else 147 size = size * 3 / 2 + 1; 148 free(string); 149 } 150 } 151} 152 153int 154listLength(ListPtr list) 155{ 156 int n = 0; 157 while(list) { 158 n++; 159 list = list->next; 160 } 161 return n; 162} 163 164ListPtr 165appendList(ListPtr first, ListPtr second) 166{ 167 ListPtr current; 168 169 if(second == NULL) 170 return first; 171 172 if(first == NULL) 173 return second; 174 175 for(current = first; current->next; current = current->next) 176 ; 177 178 current->next = second; 179 return first; 180} 181 182ListPtr 183makeList(char **a, int n, ListPtr old, int begin) 184{ 185 ListPtr first, current, next; 186 int i; 187 188 if(n == 0) 189 return old; 190 191 first = malloc(sizeof(ListRec)); 192 if(!first) 193 return NULL; 194 195 first->value = a[0]; 196 first->next = NULL; 197 198 current = first; 199 for(i = 1; i < n; i++) { 200 next = malloc(sizeof(ListRec)); 201 if(!next) { 202 destroyList(first); 203 return NULL; 204 } 205 next->value = a[i]; 206 next->next = NULL; 207 208 current->next = next; 209 current = next; 210 } 211 if(begin) { 212 current->next = old; 213 return first; 214 } else { 215 return appendList(old, first); 216 } 217} 218 219ListPtr 220reverseList(ListPtr old) 221{ 222 ListPtr new = NULL, current; 223 while(old) { 224 current = old; 225 old = old->next; 226 current->next = new; 227 new = current; 228 } 229 return new; 230} 231 232/* qsort helper for sorting list entries */ 233static int 234compareListEntries(const void *a, const void *b) 235{ 236 const ListPtr lista = *(const ListPtr *) a; 237 const ListPtr listb = *(const ListPtr *) b; 238 239 return strcmp(lista->value, listb->value); 240} 241 242ListPtr 243sortList(ListPtr old) 244{ 245 int i; 246 int l = listLength(old); 247 ListPtr n; 248 ListPtr *sorted; 249 250 if (l <= 0) 251 return old; 252 253 sorted = malloc(l * sizeof(ListPtr)); 254 255 if (sorted == NULL) 256 return old; 257 258 for (n = old, i = 0; n != NULL; n = n->next) { 259 sorted[i++] = n; 260 } 261 qsort(sorted, i, sizeof(ListPtr), compareListEntries); 262 n = sorted[0]; 263 for (i = 0; i < (l - 1); i++) { 264 sorted[i]->next = sorted[i+1]; 265 } 266 sorted[i]->next = NULL; 267 free(sorted); 268 return n; 269} 270 271void 272destroyList(ListPtr old) 273{ 274 ListPtr next; 275 if(!old) 276 return; 277 while(old) { 278 next = old->next; 279 free(old); 280 old = next; 281 } 282} 283 284void 285deepDestroyList(ListPtr old) 286{ 287 ListPtr next; 288 if(!old) 289 return; 290 while(old) { 291 next = old->next; 292 free(old->value); 293 free(old); 294 old = next; 295 } 296} 297