list.c revision 245f6787
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 <stdlib.h> 24#include <stdio.h> 25#include <stdarg.h> 26#include <string.h> 27#include "list.h" 28 29int 30listMember(char *elt, ListPtr list) 31{ 32 while(list != NULL) { 33 if(strcmp(elt, list->value) == 0) 34 return 1; 35 list = list->next; 36 } 37 return 0; 38} 39 40ListPtr 41listCons(char *car, ListPtr cdr) 42{ 43 ListPtr lcar = malloc(sizeof(ListRec)); 44 if(!lcar) 45 return NULL; 46 lcar -> value = car; 47 lcar -> next = cdr; 48 return lcar; 49} 50 51ListPtr 52listAdjoin(char *car, ListPtr cdr) 53{ 54 if(listMember(car, cdr)) { 55 free(car); 56 return cdr; 57 } 58 return listCons(car, cdr); 59} 60 61char * 62dsprintf(char *f, ...) 63{ 64 va_list args; 65 char *string; 66 { 67 int n, size = 20; 68 while(1) { 69 if(size > 4096) 70 return NULL; 71 string = malloc(size); 72 if(!string) 73 return NULL; 74 va_start(args, f); 75 n = vsnprintf(string, size, f, args); 76 va_end(args); 77 if(n >= 0 && n < size) 78 return string; 79 else if(n >= size) 80 size = n + 1; 81 else 82 size = size * 3 / 2 + 1; 83 free(string); 84 } 85 } 86} 87 88 89ListPtr 90listConsF(ListPtr cdr, char *f, ...) 91{ 92 va_list args; 93 char *string; 94 { 95 int n, size = 20; 96 while(1) { 97 if(size > 4096) 98 return NULL; 99 string = malloc(size); 100 if(!string) 101 return NULL; 102 va_start(args, f); 103 n = vsnprintf(string, size, f, args); 104 va_end(args); 105 if(n >= 0 && n < size) 106 return listCons(string, cdr); 107 else if(n >= size) 108 size = n + 1; 109 else 110 size = size * 3 / 2 + 1; 111 free(string); 112 } 113 } 114} 115 116ListPtr 117listAdjoinF(ListPtr cdr, char *f, ...) 118{ 119 va_list args; 120 char *string; 121 { 122 int n, size = 20; 123 while(1) { 124 if(size > 4096) 125 return NULL; 126 string = malloc(size); 127 if(!string) 128 return NULL; 129 va_start(args, f); 130 n = vsnprintf(string, size, f, args); 131 va_end(args); 132 if(n >= 0 && n < size) 133 return listAdjoin(string, cdr); 134 else if(n >= size) 135 size = n + 1; 136 else 137 size = size * 3 / 2 + 1; 138 free(string); 139 } 140 } 141} 142 143int 144listLength(ListPtr list) 145{ 146 int n = 0; 147 while(list) { 148 n++; 149 list = list->next; 150 } 151 return n; 152} 153 154ListPtr 155appendList(ListPtr first, ListPtr second) 156{ 157 ListPtr current; 158 159 if(second == NULL) 160 return first; 161 162 if(first == NULL) 163 return second; 164 165 for(current = first; current->next; current = current->next) 166 ; 167 168 current->next = second; 169 return first; 170} 171 172ListPtr 173makeList(char **a, int n, ListPtr old, int begin) 174{ 175 ListPtr first, current, next; 176 int i; 177 178 if(n == 0) 179 return old; 180 181 first = malloc(sizeof(ListRec)); 182 if(!first) 183 return NULL; 184 185 first->value = a[0]; 186 first->next = NULL; 187 188 current = first; 189 for(i = 1; i < n; i++) { 190 next = malloc(sizeof(ListRec)); 191 if(!next) { 192 destroyList(first); 193 return NULL; 194 } 195 next->value = a[i]; 196 next->next = NULL; 197 198 current->next = next; 199 current = next; 200 } 201 if(begin) { 202 current->next = old; 203 return first; 204 } else { 205 return appendList(old, first); 206 } 207} 208 209ListPtr 210reverseList(ListPtr old) 211{ 212 ListPtr new = NULL, current; 213 while(old) { 214 current = old; 215 old = old->next; 216 current->next = new; 217 new = current; 218 } 219 return new; 220} 221 222/* qsort helper for sorting list entries */ 223static int 224compareListEntries(const void *a, const void *b) 225{ 226 const ListPtr lista = *(const ListPtr *) a; 227 const ListPtr listb = *(const ListPtr *) b; 228 229 return strcmp(lista->value, listb->value); 230} 231 232ListPtr 233sortList(ListPtr old) 234{ 235 int i; 236 int l = listLength(old); 237 ListPtr n; 238 ListPtr *sorted = malloc(l * sizeof(ListPtr)); 239 240 if (sorted == NULL) 241 return old; 242 243 for (n = old, i = 0; n != NULL; n = n->next) { 244 sorted[i++] = n; 245 } 246 qsort(sorted, i, sizeof(ListPtr), compareListEntries); 247 n = sorted[0]; 248 for (i = 0; i < (l - 1); i++) { 249 sorted[i]->next = sorted[i+1]; 250 } 251 sorted[i]->next = NULL; 252 free(sorted); 253 return n; 254} 255 256void 257destroyList(ListPtr old) 258{ 259 ListPtr next; 260 if(!old) 261 return; 262 while(old) { 263 next = old->next; 264 free(old); 265 old = next; 266 } 267} 268 269void 270deepDestroyList(ListPtr old) 271{ 272 ListPtr next; 273 if(!old) 274 return; 275 while(old) { 276 next = old->next; 277 free(old->value); 278 free(old); 279 old = next; 280 } 281} 282