Correcting some typos, and an obsolete comment.
[privoxy.git] / list.c
1 const char list_rcs[] = "$Id: list.c,v NOT CHECKED IN $";
2 /*********************************************************************
3  *
4  * File        :  $Source: /cvsroot/ijbswa/current/list.c,v $
5  *
6  * Purpose     :  Declares functions to handle lists.
7  *                Functions declared include:
8  *                   `destroy_list', `enlist' and `list_to_text'
9  *
10  * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
11  *                IJBSWA team.  http://ijbswa.sourceforge.net
12  *
13  *                Based on the Internet Junkbuster originally written
14  *                by and Copyright (C) 1997 Anonymous Coders and 
15  *                Junkbusters Corporation.  http://www.junkbusters.com
16  *
17  *                This program is free software; you can redistribute it 
18  *                and/or modify it under the terms of the GNU General
19  *                Public License as published by the Free Software
20  *                Foundation; either version 2 of the License, or (at
21  *                your option) any later version.
22  *
23  *                This program is distributed in the hope that it will
24  *                be useful, but WITHOUT ANY WARRANTY; without even the
25  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
26  *                PARTICULAR PURPOSE.  See the GNU General Public
27  *                License for more details.
28  *
29  *                The GNU General Public License should be included with
30  *                this file.  If not, you can view it at
31  *                http://www.gnu.org/copyleft/gpl.html
32  *                or write to the Free Software Foundation, Inc., 59
33  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
34  *
35  * Revisions   :
36  *    $Log: list.c,v $
37  *
38  *********************************************************************/
39 \f
40
41 #include "config.h"
42
43 #include <stdio.h>
44 #include <sys/types.h>
45 #include <stdlib.h>
46 #include <ctype.h>
47 #include <string.h>
48
49 #ifndef _WIN32
50 #include <unistd.h>
51 #endif
52
53 #include "project.h"
54 #include "jcc.h"
55 #include "list.h"
56 #include "miscutil.h"
57
58 const char list_h_rcs[] = LIST_H_VERSION;
59
60 /*********************************************************************
61  *
62  * Function    :  enlist
63  *
64  * Description :  Append a string into a specified string list.
65  *
66  * Parameters  :
67  *          1  :  header = pointer to list 'dummy' header
68  *          2  :  str = string to add to the list (maybe NULL)
69  *
70  * Returns     :  N/A
71  *
72  *********************************************************************/
73 void enlist(struct list *header, const char *str)
74 {
75    struct list *cur = (struct list *)malloc(sizeof(*cur));
76    struct list *last;
77
78    if (cur)
79    {
80       cur->str  = (str ? strdup(str) : NULL);
81       cur->next = NULL;
82
83       last = header->last;
84       if (last == NULL)
85       {
86          last = header;
87       }
88
89       last->next   = cur;
90       header->last = cur;
91    }
92
93 }
94
95
96 /*********************************************************************
97  *
98  * Function    :  enlist_unique
99  *
100  * Description :  Append a string into a specified string list,
101  *                if & only if it's not there already.
102  *
103  * Parameters  :
104  *          1  :  header = pointer to list 'dummy' header
105  *          2  :  str = string to add to the list (maybe NULL)
106  *
107  * Returns     :  N/A
108  *
109  *********************************************************************/
110 void enlist_unique(struct list *header, const char *str)
111 {
112    struct list *last;
113    struct list *cur = header->next;
114
115    while (cur != NULL)
116    {
117       if ((cur->str != NULL) && (0 == strcmp(str, cur->str)))
118       {
119          /* Already there */
120          return;
121       }
122       cur = cur->next;
123    }
124
125    cur = (struct list *)malloc(sizeof(*cur));
126
127    if (cur != NULL)
128    {
129       cur->str  = (str ? strdup(str) : NULL); /* FIXME check retval */
130       cur->next = NULL;
131
132       last = header->last;
133       if (last == NULL)
134       {
135          last = header;
136       }
137       last->next   = cur;
138       header->last = cur;
139    }
140 }
141
142
143 /*********************************************************************
144  *
145  * Function    :  destroy_list
146  *
147  * Description :  Destroy a string list (opposite of enlist)
148  *
149  * Parameters  :
150  *          1  :  header = pointer to list 'dummy' header
151  *
152  * Returns     :  N/A
153  *
154  *********************************************************************/
155 void destroy_list(struct list *header)
156 {
157    struct list *p, *n;
158
159    for (p = header->next; p ; p = n)
160    {
161       n = p->next;
162       freez(p->str);
163       free(p);
164    }
165
166    memset(header, '\0', sizeof(*header));
167
168 }
169
170
171 /*********************************************************************
172  *
173  * Function    :  list_to_text
174  *
175  * Description :  "Flaten" a string list into 1 long \r\n delimited string.
176  *
177  * Parameters  :
178  *          1  :  h = pointer to list 'dummy' header
179  *
180  * Returns     :  NULL on malloc error, else new long string.
181  *
182  *********************************************************************/
183 char *list_to_text(struct list *h)
184 {
185    struct list *p;
186    char *ret = NULL;
187    char *s;
188    int size;
189
190    size = 0;
191
192    for (p = h->next; p ; p = p->next)
193    {
194       if (p->str)
195       {
196          size += strlen(p->str) + 2;
197       }
198    }
199
200    if ((ret = (char *)malloc(size + 1)) == NULL)
201    {
202       return(NULL);
203    }
204
205    ret[size] = '\0';
206
207    s = ret;
208
209    for (p = h->next; p ; p = p->next)
210    {
211       if (p->str)
212       {
213          strcpy(s, p->str);
214          s += strlen(s);
215          *s++ = '\r'; *s++ = '\n';
216       }
217    }
218
219    return(ret);
220
221 }
222
223
224 /*********************************************************************
225  *
226  * Function    :  list_remove_item
227  *
228  * Description :  Remove a string from a specified string list.
229  *
230  * Parameters  :
231  *          1  :  header = pointer to list 'dummy' header
232  *          2  :  str = string to remove from the list
233  *
234  * Returns     :  Number of times it was removed.
235  *
236  *********************************************************************/
237 int list_remove_item(struct list *header, const char *str)
238 {
239    struct list *prev = header;
240    struct list *cur = prev->next;
241    int count = 0;
242
243    while (cur != NULL)
244    {
245       if ((cur->str != NULL) && (0 == strcmp(str, cur->str)))
246       {
247          count++;
248
249          prev->next = cur->next;
250          free(cur->str);
251          free(cur);
252       }
253       else
254       {
255          prev = cur;
256       }
257       cur = prev->next;
258    }
259
260    header->last = prev;
261
262    return count;
263 }
264
265
266 /*********************************************************************
267  *
268  * Function    :  list_remove_list
269  *
270  * Description :  Remove all strings in one list from another list.
271  *                This is currently a brute-force algorithm
272  *                (it compares every pair of strings).
273  *
274  * Parameters  :
275  *          1  :  dest = list to change
276  *          2  :  src = list of strings to remove
277  *
278  * Returns     :  Total number of strings removed.
279  *
280  *********************************************************************/
281 int list_remove_list(struct list *dest, const struct list *src)
282 {
283    struct list *cur = src->next;
284    int count = 0;
285
286    while (cur != NULL)
287    {
288       if (cur->str != NULL)
289       {
290          count += list_remove_item(dest, cur->str);
291       }
292       cur = cur->next;
293    }
294
295    return count;
296 }
297
298
299 /*********************************************************************
300  *
301  * Function    :  list_duplicate
302  *
303  * Description :  Duplicate a string list
304  *
305  * Parameters  :
306  *          1  :  dest = pointer to destination for copy.  Caller allocs.
307  *          2  :  src = pointer to source for copy.
308  *
309  * Returns     :  N/A
310  *
311  *********************************************************************/
312 void list_duplicate(struct list *dest, const struct list *src)
313 {
314    struct list * cur_src = src->next;
315    struct list * cur_dest = dest;
316
317    memset(dest, '\0', sizeof(*dest));
318
319    while (cur_src)
320    {
321       cur_dest = cur_dest->next = (struct list *)zalloc(sizeof(*cur_dest));
322       if (cur_dest == NULL)
323       {
324          return;
325       }
326       cur_dest->str = strdup(cur_src->str);
327       cur_src = cur_src->next;
328    }
329
330    dest->last = cur_dest;
331
332 }
333
334
335 /*********************************************************************
336  *
337  * Function    :  list_append_list_unique
338  *
339  * Description :  Append a string list to another list
340  *
341  * Parameters  :
342  *          1  :  dest = pointer to destination for merge.  Caller allocs.
343  *          2  :  src = pointer to source for merge.
344  *
345  * Returns     :  N/A
346  *
347  *********************************************************************/
348 void list_append_list_unique(struct list *dest, const struct list *src)
349 {
350    struct list * cur = src->next;
351
352    while (cur)
353    {
354       enlist_unique(dest, cur->str);
355       cur = cur->next;
356    }
357 }
358
359
360 /*********************************************************************
361  *
362  * Function    :  destroy_list_share
363  *
364  * Description :  Destroy a string list (opposite of enlist)
365  *
366  * Parameters  :
367  *          1  :  h = pointer to list 'dummy' header
368  *
369  * Returns     :  N/A
370  *
371  *********************************************************************/
372 void destroy_list_share(struct list_share *h)
373 {
374    struct list_share *p, *n;
375
376    for (p = h->next; p ; p = n)
377    {
378       n = p->next;
379       free(p);
380    }
381
382    memset(h, '\0', sizeof(*h));
383
384 }
385
386
387 /*********************************************************************
388  *
389  * Function    :  enlist_share
390  *
391  * Description :  Append a string into a specified string list.
392  *
393  * Parameters  :
394  *          1  :  header = pointer to list 'dummy' header
395  *          2  :  str = string to add to the list (maybe NULL)
396  *
397  * Returns     :  N/A
398  *
399  *********************************************************************/
400 void enlist_share(struct list_share *header, const char *str)
401 {
402    struct list_share *cur = (struct list_share *)malloc(sizeof(*cur));
403    struct list_share *last;
404
405    if (cur)
406    {
407       cur->str  = (str ? strdup(str) : NULL);
408       cur->next = NULL;
409
410       last = header->last;
411       if (last == NULL)
412       {
413          last = header;
414       }
415
416       last->next   = cur;
417       header->last = cur;
418    }
419
420 }
421
422
423 /*********************************************************************
424  *
425  * Function    :  enlist_unique_share
426  *
427  * Description :  Append a string into a specified string list,
428  *                if & only if it's not there already.
429  *
430  * Parameters  :
431  *          1  :  header = pointer to list 'dummy' header
432  *          2  :  str = string to add to the list (maybe NULL)
433  *
434  * Returns     :  N/A
435  *
436  *********************************************************************/
437 void enlist_unique_share(struct list_share *header, const char *str)
438 {
439    struct list_share *last;
440    struct list_share *cur = header->next;
441
442    while (cur != NULL)
443    {
444       if ((cur->str != NULL) && (0 == strcmp(str, cur->str)))
445       {
446          /* Already there */
447          return;
448       }
449       cur = cur->next;
450    }
451
452    cur = (struct list_share *)malloc(sizeof(*cur));
453
454    if (cur != NULL)
455    {
456       cur->str  = str;
457       cur->next = NULL;
458
459       last = header->last;
460       if (last == NULL)
461       {
462          last = header;
463       }
464       last->next   = cur;
465       header->last = cur;
466    }
467 }
468
469
470 /*********************************************************************
471  *
472  * Function    :  list_append_list_unique_share
473  *
474  * Description :  Append a string list to another list
475  *
476  * Parameters  :
477  *          1  :  dest = pointer to destination for merge.  Caller allocs.
478  *          2  :  src = pointer to source for merge.
479  *
480  * Returns     :  N/A
481  *
482  *********************************************************************/
483 void list_append_list_unique_share(struct list_share *dest, const struct list *src)
484 {
485    struct list * cur = src->next;
486
487    while (cur)
488    {
489       enlist_unique_share(dest, cur->str);
490       cur = cur->next;
491    }
492 }
493
494
495 /*********************************************************************
496  *
497  * Function    :  list_remove_item_share
498  *
499  * Description :  Remove a string from a specified string list.
500  *
501  * Parameters  :
502  *          1  :  header = pointer to list 'dummy' header
503  *          2  :  str = string to remove from the list
504  *
505  * Returns     :  Number of times it was removed.
506  *
507  *********************************************************************/
508 int list_remove_item_share(struct list_share *header, const char *str)
509 {
510    struct list_share *prev = header;
511    struct list_share *cur = prev->next;
512    int count = 0;
513
514    while (cur != NULL)
515    {
516       if ((cur->str != NULL) && (0 == strcmp(str, cur->str)))
517       {
518          count++;
519
520          prev->next = cur->next;
521          free(cur);
522       }
523       else
524       {
525          prev = cur;
526       }
527       cur = prev->next;
528    }
529
530    header->last = prev;
531
532    return count;
533 }
534
535
536 /*********************************************************************
537  *
538  * Function    :  list_remove_list_share
539  *
540  * Description :  Remove all strings in one list from another list.
541  *                This is currently a brute-force algorithm
542  *                (it compares every pair of strings).
543  *
544  * Parameters  :
545  *          1  :  dest = list to change
546  *          2  :  src = list of strings to remove
547  *
548  * Returns     :  Total number of strings removed.
549  *
550  *********************************************************************/
551 int list_remove_list_share(struct list_share *dest, const struct list *src)
552 {
553    struct list *cur = src->next;
554    int count = 0;
555
556    while (cur != NULL)
557    {
558       if (cur->str != NULL)
559       {
560          count += list_remove_item_share(dest, cur->str);
561       }
562       cur = cur->next;
563    }
564
565    return count;
566 }
567
568
569 /*********************************************************************
570  *
571  * Function    :  list_duplicate_share
572  *
573  * Description :  Duplicate a string list
574  *
575  * Parameters  :
576  *          1  :  dest = pointer to destination for copy.  Caller allocs.
577  *          2  :  src = pointer to source for copy.
578  *
579  * Returns     :  N/A
580  *
581  *********************************************************************/
582 void list_duplicate_share(struct list_share *dest, const struct list *src)
583 {
584    struct list * cur_src = src->next;
585    struct list_share * cur_dest = dest;
586
587    memset(dest, '\0', sizeof(*dest));
588
589    while (cur_src)
590    {
591       cur_dest = cur_dest->next = (struct list_share *)zalloc(sizeof(*cur_dest));
592       if (cur_dest == NULL)
593       {
594          return;
595       }
596       cur_dest->str = cur_src->str;
597       cur_src = cur_src->next;
598    }
599
600    dest->last = cur_dest;
601
602 }
603