255d6fd4b3426be5c2105d3fd6bae62f0857b229
[privoxy.git] / list.c
1 const char list_rcs[] = "$Id: list.c,v 1.5 2001/06/29 21:45:41 oes Exp $";
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  *    Revision 1.5  2001/06/29 21:45:41  oes
38  *    Indentation, CRLF->LF, Tab-> Space
39  *
40  *    Revision 1.4  2001/06/29 13:30:22  oes
41  *    - Added Convenience function enlist_unique_header(),
42  *      which takes the Header name and value as separate
43  *      arguments and thus saves the pain of sprintf()ing
44  *      and determining the Header name length to enlist_unique
45  *    - Improved comments
46  *    - Removed logentry from cancelled commit
47  *
48  *    Revision 1.3  2001/06/03 19:12:24  oes
49  *    functions for new struct map, extended enlist_unique
50  *
51  *    Revision 1.2  2001/06/01 18:49:17  jongfoster
52  *    Replaced "list_share" with "list" - the tiny memory gain was not
53  *    worth the extra complexity.
54  *
55  *    Revision 1.1  2001/05/31 21:11:53  jongfoster
56  *    - Moved linked list support to new "list.c" file.
57  *      Structure definitions are still in project.h,
58  *      function prototypes are now in "list.h".
59  *    - Added support for "struct list_share", which is identical
60  *      to "struct list" except it saves memory by not duplicating
61  *      the strings.  Obviously, this only works if there is some
62  *      other way of managing the memory used by the strings.
63  *      (These list_share lists are used for lists which last
64  *      for only 1 request, and where all the list entries are
65  *      just coming directly from entries in the actionsfile.)
66  *      Note that you still need to destroy list_share lists
67  *      properly to free the nodes - it's only the strings
68  *      which are shared.
69  *
70  *
71  *********************************************************************/
72 \f
73
74 #include "config.h"
75
76 #include <stdio.h>
77 #include <sys/types.h>
78 #include <stdlib.h>
79 #include <ctype.h>
80 #include <string.h>
81
82 #ifndef _WIN32
83 #include <unistd.h>
84 #endif
85
86 #include "project.h"
87 #include "jcc.h"
88 #include "list.h"
89 #include "miscutil.h"
90
91 const char list_h_rcs[] = LIST_H_VERSION;
92
93 /*********************************************************************
94  *
95  * Function    :  enlist
96  *
97  * Description :  Append a string into a specified string list.
98  *
99  * Parameters  :
100  *          1  :  header = pointer to list 'dummy' header
101  *          2  :  str = string to add to the list (maybe NULL)
102  *
103  * Returns     :  N/A
104  *
105  *********************************************************************/
106 void enlist(struct list *header, const char *str)
107 {
108    struct list *cur = (struct list *)malloc(sizeof(*cur));
109    struct list *last;
110
111    if (cur)
112    {
113       cur->str  = (str ? strdup(str) : NULL);
114       cur->next = NULL;
115
116       last = header->last;
117       if (last == NULL)
118       {
119          last = header;
120       }
121
122       last->next   = cur;
123       header->last = cur;
124    }
125
126 }
127
128
129 /*********************************************************************
130  *
131  * Function    :  enlist_first
132  *
133  * Description :  Append a string as first element into a specified
134  *                string list.
135  *
136  * Parameters  :
137  *          1  :  header = pointer to list 'dummy' header
138  *          2  :  str = string to add to the list (maybe NULL)
139  *
140  * Returns     :  N/A
141  *
142  *********************************************************************/
143 void enlist_first(struct list *header, const char *str)
144 {
145    struct list *cur = (struct list *)malloc(sizeof(*cur));
146
147    if (cur)
148    {
149       cur->str  = (str ? strdup(str) : NULL);
150       cur->next = header->next;
151
152       header->next = cur;
153       if (header->last == NULL)
154       {
155          header->last = cur;
156       }
157    }
158
159 }
160
161
162 /*********************************************************************
163  *
164  * Function    :  enlist_unique
165  *
166  * Description :  Append a string into a specified string list,
167  *                if & only if it's not there already.
168  *                If the n argument is nonzero, only compare up to
169  *                the nth character. 
170  *
171  * Parameters  :
172  *          1  :  header = pointer to list 'dummy' header
173  *          2  :  str = string to add to the list (maybe NULL)
174  *          3  :  n = number of chars to use for uniqueness test
175  *
176  * Returns     :  N/A
177  *
178  *********************************************************************/
179 void enlist_unique(struct list *header, const char *str, int n)
180 {
181    struct list *last;
182    struct list *cur = header->next;
183
184    while (cur != NULL)
185    {
186       if ((cur->str != NULL) && (
187          (n && (0 == strncmp(str, cur->str, n))) || 
188          (!n && (0 == strcmp(str, cur->str)))))
189       {
190          /* Already there */
191          return;
192       }
193       cur = cur->next;
194    }
195
196    cur = (struct list *)malloc(sizeof(*cur));
197
198    if (cur != NULL)
199    {
200       cur->str  = (str ? strdup(str) : NULL); /* FIXME check retval */
201       cur->next = NULL;
202
203       last = header->last;
204       if (last == NULL)
205       {
206          last = header;
207       }
208       last->next   = cur;
209       header->last = cur;
210    }
211 }
212
213
214 /*********************************************************************
215  *
216  * Function    :  enlist_unique_header
217  *
218  * Description :  Make a HTTP header from the two strings name and value,
219  *                and append the result into a specified string list,
220  *                if & only if there isn't already a header with that name.
221  *
222  * Parameters  :
223  *          1  :  header = pointer to list 'dummy' header
224  *          2  :  first = first string to add to the list (maybe NULL)
225  *          3  :  second = number of chars to use for uniqueness test
226  *
227  * Returns     :  N/A
228  *
229  *********************************************************************/
230 void enlist_unique_header(struct list *header, const char *name, const char *value)
231 {
232    struct list *last;
233    struct list *cur = header->next;
234    int length;
235    char *dummy;
236
237    if (name == NULL || value == NULL) return;
238
239    dummy = strdup(name);
240    dummy = strsav(dummy, ": ");
241    length = strlen(dummy);
242
243    while (cur != NULL)
244    {
245       if ((cur->str != NULL) && 
246                 (0 == strncmp(dummy, cur->str, length)))
247       {
248          /* Already there */
249          return;
250       }
251       cur = cur->next;
252    }
253
254    cur = (struct list *)malloc(sizeof(*cur));
255
256    if (cur != NULL)
257    {
258       cur->str  = strsav(dummy, value);
259       cur->next = NULL;
260
261       last = header->last;
262       if (last == NULL)
263       {
264          last = header;
265       }
266       last->next   = cur;
267       header->last = cur;
268    }
269 }
270
271
272 /*********************************************************************
273  *
274  * Function    :  destroy_list
275  *
276  * Description :  Destroy a string list (opposite of enlist)
277  *
278  * Parameters  :
279  *          1  :  header = pointer to list 'dummy' header
280  *
281  * Returns     :  N/A
282  *
283  *********************************************************************/
284 void destroy_list(struct list *header)
285 {
286    struct list *p, *n;
287
288    for (p = header->next; p ; p = n)
289    {
290       n = p->next;
291       freez(p->str);
292       free(p);
293    }
294
295    memset(header, '\0', sizeof(*header));
296
297 }
298
299
300 /*********************************************************************
301  *
302  * Function    :  list_to_text
303  *
304  * Description :  "Flaten" a string list into 1 long \r\n delimited string,
305  *                adding an empty line at the end.
306  *
307  * Parameters  :
308  *          1  :  h = pointer to list 'dummy' header
309  *
310  * Returns     :  NULL on malloc error, else new long string.
311  *
312  *********************************************************************/
313 char *list_to_text(struct list *h)
314 {
315    struct list *p;
316    char *ret = NULL;
317    char *s;
318    int size = 2;
319
320    for (p = h->next; p ; p = p->next)
321    {
322       if (p->str)
323       {
324          size += strlen(p->str) + 2;
325       }
326    }
327
328    if ((ret = (char *)malloc(size + 1)) == NULL)
329    {
330       return(NULL);
331    }
332
333    ret[size] = '\0';
334
335    s = ret;
336
337    for (p = h->next; p ; p = p->next)
338    {
339       if (p->str)
340       {
341          strcpy(s, p->str);
342          s += strlen(s);
343          *s++ = '\r'; *s++ = '\n';
344       }
345    }
346    *s++ = '\r'; *s++ = '\n';
347
348    return(ret);
349
350 }
351
352
353 /*********************************************************************
354  *
355  * Function    :  list_remove_item
356  *
357  * Description :  Remove a string from a specified string list.
358  *
359  * Parameters  :
360  *          1  :  header = pointer to list 'dummy' header
361  *          2  :  str = string to remove from the list
362  *
363  * Returns     :  Number of times it was removed.
364  *
365  *********************************************************************/
366 int list_remove_item(struct list *header, const char *str)
367 {
368    struct list *prev = header;
369    struct list *cur = prev->next;
370    int count = 0;
371
372    while (cur != NULL)
373    {
374       if ((cur->str != NULL) && (0 == strcmp(str, cur->str)))
375       {
376          count++;
377
378          prev->next = cur->next;
379          free(cur->str);
380          free(cur);
381       }
382       else
383       {
384          prev = cur;
385       }
386       cur = prev->next;
387    }
388
389    header->last = prev;
390
391    return count;
392 }
393
394
395 /*********************************************************************
396  *
397  * Function    :  list_remove_list
398  *
399  * Description :  Remove all strings in one list from another list.
400  *                This is currently a brute-force algorithm
401  *                (it compares every pair of strings).
402  *
403  * Parameters  :
404  *          1  :  dest = list to change
405  *          2  :  src = list of strings to remove
406  *
407  * Returns     :  Total number of strings removed.
408  *
409  *********************************************************************/
410 int list_remove_list(struct list *dest, const struct list *src)
411 {
412    struct list *cur = src->next;
413    int count = 0;
414
415    while (cur != NULL)
416    {
417       if (cur->str != NULL)
418       {
419          count += list_remove_item(dest, cur->str);
420       }
421       cur = cur->next;
422    }
423
424    return count;
425 }
426
427
428 /*********************************************************************
429  *
430  * Function    :  list_duplicate
431  *
432  * Description :  Duplicate a string list
433  *
434  * Parameters  :
435  *          1  :  dest = pointer to destination for copy.  Caller allocs.
436  *          2  :  src = pointer to source for copy.
437  *
438  * Returns     :  N/A
439  *
440  *********************************************************************/
441 void list_duplicate(struct list *dest, const struct list *src)
442 {
443    struct list * cur_src = src->next;
444    struct list * cur_dest = dest;
445
446    memset(dest, '\0', sizeof(*dest));
447
448    while (cur_src)
449    {
450       cur_dest = cur_dest->next = (struct list *)zalloc(sizeof(*cur_dest));
451       if (cur_dest == NULL)
452       {
453          return;
454       }
455       cur_dest->str = strdup(cur_src->str);
456       cur_src = cur_src->next;
457    }
458
459    dest->last = cur_dest;
460
461 }
462
463
464 /*********************************************************************
465  *
466  * Function    :  list_append_list_unique
467  *
468  * Description :  Append a string list to another list.
469  *                Duplicate items are not added.
470  *
471  * Parameters  :
472  *          1  :  dest = pointer to destination for merge.  Caller allocs.
473  *          2  :  src = pointer to source for merge.
474  *
475  * Returns     :  N/A
476  *
477  *********************************************************************/
478 void list_append_list_unique(struct list *dest, const struct list *src)
479 {
480    struct list * cur = src->next;
481
482    while (cur)
483    {
484       enlist_unique(dest, cur->str, 0);
485       cur = cur->next;
486    }
487 }
488
489
490 /*********************************************************************
491  *
492  * Function    :  map
493  *
494  * Description :  Add a mapping from given name to given value to a
495  *                given map.
496  *
497  *                Note: Since all strings will be free()d in free_map()
498  *                      later, use the copy flags for constants or
499  *                      strings that will be independantly free()d.
500  *
501  * Parameters  :
502  *          1  :  map = map to add to
503  *          2  :  name = name to add
504  *          3  :  nc = flag set if a copy of name should be used
505  *          4  :  value = value to add
506  *          5  :  vc = flag set if a copy of value should be used
507  *
508  * Returns     :  pointer to extended map, or NULL if failiure
509  *
510  *********************************************************************/
511 struct map *map(struct map *map, char *name, int nc, char *value, int vc)
512 {
513    struct map *cur;
514
515    if (NULL == (cur = zalloc(sizeof(*cur))))
516    {
517       return(NULL);
518    }
519
520    cur->name  = nc ? strdup(name) : name;
521    cur->value = vc ? strdup(value) : value;
522    cur->next = map;
523
524    return(cur);
525
526 }
527
528
529 /*********************************************************************
530  *
531  * Function    :  lookup
532  *
533  * Description :  Look up an item with a given name in a map, and
534  *                return its value
535  *
536  * Parameters  :
537  *          1  :  name = name parameter to look for
538  *
539  * Returns     :  the value if found, else the empty string
540  *
541  *********************************************************************/
542 char *lookup(struct map *map, char *name)
543 {
544    struct map *p = map;
545
546    while (p)
547    {
548       if (!strcmp(name, p->name))
549       {
550          return p->value;
551       }
552       p = p->next;
553    }
554    return "";
555
556 }
557
558
559 /*********************************************************************
560  *
561  * Function    :  free_map
562  *
563  * Description :  Free the memory occupied by a map and its
564  *                depandant strings
565  *
566  * Parameters  :
567  *          1  :  list = list to bee freed
568  *
569  * Returns     :  N/A
570  *
571  *********************************************************************/
572 void free_map(struct map *map)
573 {
574    struct map *p = map;
575
576    while (p)
577    {
578       free(p->name);
579       free(p->value);
580
581       map = p->next;
582       free(p);
583       p = map;
584    }
585
586 }
587
588
589 /*
590   Local Variables:
591   tab-width: 3
592   end:
593 */