1 const char list_rcs[] = "$Id: list.c,v 1.7 2001/08/05 16:06:20 jongfoster Exp $";
2 /*********************************************************************
4 * File : $Source: /cvsroot/ijbswa/current/list.c,v $
6 * Purpose : Declares functions to handle lists.
7 * Functions declared include:
8 * `destroy_list', `enlist' and `list_to_text'
10 * Copyright : Written by and Copyright (C) 2001 the SourceForge
11 * IJBSWA team. http://ijbswa.sourceforge.net
13 * Based on the Internet Junkbuster originally written
14 * by and Copyright (C) 1997 Anonymous Coders and
15 * Junkbusters Corporation. http://www.junkbusters.com
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.
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.
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.
37 * Revision 1.7 2001/08/05 16:06:20 jongfoster
38 * Modifiying "struct map" so that there are now separate header and
39 * "map_entry" structures. This means that functions which modify a
40 * map no longer need to return a pointer to the modified map.
41 * Also, it no longer reverses the order of the entries (which may be
42 * important with some advanced template substitutions).
44 * Revision 1.6 2001/07/31 14:44:51 oes
45 * list_to_text() now appends empty line at end
47 * Revision 1.5 2001/06/29 21:45:41 oes
48 * Indentation, CRLF->LF, Tab-> Space
50 * Revision 1.4 2001/06/29 13:30:22 oes
51 * - Added Convenience function enlist_unique_header(),
52 * which takes the Header name and value as separate
53 * arguments and thus saves the pain of sprintf()ing
54 * and determining the Header name length to enlist_unique
56 * - Removed logentry from cancelled commit
58 * Revision 1.3 2001/06/03 19:12:24 oes
59 * functions for new struct map, extended enlist_unique
61 * Revision 1.2 2001/06/01 18:49:17 jongfoster
62 * Replaced "list_share" with "list" - the tiny memory gain was not
63 * worth the extra complexity.
65 * Revision 1.1 2001/05/31 21:11:53 jongfoster
66 * - Moved linked list support to new "list.c" file.
67 * Structure definitions are still in project.h,
68 * function prototypes are now in "list.h".
69 * - Added support for "struct list_share", which is identical
70 * to "struct list" except it saves memory by not duplicating
71 * the strings. Obviously, this only works if there is some
72 * other way of managing the memory used by the strings.
73 * (These list_share lists are used for lists which last
74 * for only 1 request, and where all the list entries are
75 * just coming directly from entries in the actionsfile.)
76 * Note that you still need to destroy list_share lists
77 * properly to free the nodes - it's only the strings
81 *********************************************************************/
87 #include <sys/types.h>
101 #include "miscutil.h"
103 const char list_h_rcs[] = LIST_H_VERSION;
106 /*********************************************************************
110 * Description : Append a string into a specified string list.
113 * 1 : header = pointer to list 'dummy' header
114 * 2 : str = string to add to the list (maybe NULL)
118 *********************************************************************/
119 void enlist(struct list *header, const char *str)
121 struct list *cur = (struct list *)malloc(sizeof(*cur));
126 cur->str = (str ? strdup(str) : NULL);
142 /*********************************************************************
144 * Function : enlist_first
146 * Description : Append a string as first element into a specified
150 * 1 : header = pointer to list 'dummy' header
151 * 2 : str = string to add to the list (maybe NULL)
155 *********************************************************************/
156 void enlist_first(struct list *header, const char *str)
158 struct list *cur = (struct list *)malloc(sizeof(*cur));
162 cur->str = (str ? strdup(str) : NULL);
163 cur->next = header->next;
166 if (header->last == NULL)
175 /*********************************************************************
177 * Function : enlist_unique
179 * Description : Append a string into a specified string list,
180 * if & only if it's not there already.
181 * If the n argument is nonzero, only compare up to
185 * 1 : header = pointer to list 'dummy' header
186 * 2 : str = string to add to the list (maybe NULL)
187 * 3 : n = number of chars to use for uniqueness test
191 *********************************************************************/
192 void enlist_unique(struct list *header, const char *str, int n)
195 struct list *cur = header->next;
199 if ((cur->str != NULL) && (
200 (n && (0 == strncmp(str, cur->str, n))) ||
201 (!n && (0 == strcmp(str, cur->str)))))
209 cur = (struct list *)malloc(sizeof(*cur));
213 cur->str = (str ? strdup(str) : NULL); /* FIXME check retval */
227 /*********************************************************************
229 * Function : enlist_unique_header
231 * Description : Make a HTTP header from the two strings name and value,
232 * and append the result into a specified string list,
233 * if & only if there isn't already a header with that name.
236 * 1 : header = pointer to list 'dummy' header
237 * 2 : name = name of header to be added
238 * 3 : value = value of header to be added
242 *********************************************************************/
243 void enlist_unique_header(struct list *header, const char *name, const char *value)
246 struct list *cur = header->next;
250 if (name == NULL || value == NULL) return;
252 dummy = strdup(name);
253 dummy = strsav(dummy, ": ");
254 length = strlen(dummy);
258 if ((cur->str != NULL) &&
259 (0 == strncmp(dummy, cur->str, length)))
267 cur = (struct list *)malloc(sizeof(*cur));
271 cur->str = strsav(dummy, value);
285 /*********************************************************************
287 * Function : destroy_list
289 * Description : Destroy a string list (opposite of enlist)
292 * 1 : header = pointer to list 'dummy' header
296 *********************************************************************/
297 void destroy_list(struct list *header)
301 for (p = header->next; p ; p = n)
308 memset(header, '\0', sizeof(*header));
313 /*********************************************************************
315 * Function : list_to_text
317 * Description : "Flaten" a string list into 1 long \r\n delimited string,
318 * adding an empty line at the end.
321 * 1 : h = pointer to list 'dummy' header
323 * Returns : NULL on malloc error, else new long string.
325 *********************************************************************/
326 char *list_to_text(struct list *h)
333 for (p = h->next; p ; p = p->next)
337 size += strlen(p->str) + 2;
341 if ((ret = (char *)malloc(size + 1)) == NULL)
350 for (p = h->next; p ; p = p->next)
356 *s++ = '\r'; *s++ = '\n';
359 *s++ = '\r'; *s++ = '\n';
366 /*********************************************************************
368 * Function : list_remove_item
370 * Description : Remove a string from a specified string list.
373 * 1 : header = pointer to list 'dummy' header
374 * 2 : str = string to remove from the list
376 * Returns : Number of times it was removed.
378 *********************************************************************/
379 int list_remove_item(struct list *header, const char *str)
381 struct list *prev = header;
382 struct list *cur = prev->next;
387 if ((cur->str != NULL) && (0 == strcmp(str, cur->str)))
391 prev->next = cur->next;
408 /*********************************************************************
410 * Function : list_remove_list
412 * Description : Remove all strings in one list from another list.
413 * This is currently a brute-force algorithm
414 * (it compares every pair of strings).
417 * 1 : dest = list to change
418 * 2 : src = list of strings to remove
420 * Returns : Total number of strings removed.
422 *********************************************************************/
423 int list_remove_list(struct list *dest, const struct list *src)
425 struct list *cur = src->next;
430 if (cur->str != NULL)
432 count += list_remove_item(dest, cur->str);
441 /*********************************************************************
443 * Function : list_duplicate
445 * Description : Duplicate a string list
448 * 1 : dest = pointer to destination for copy. Caller allocs.
449 * 2 : src = pointer to source for copy.
453 *********************************************************************/
454 void list_duplicate(struct list *dest, const struct list *src)
456 struct list * cur_src = src->next;
457 struct list * cur_dest = dest;
459 memset(dest, '\0', sizeof(*dest));
463 cur_dest = cur_dest->next = (struct list *)zalloc(sizeof(*cur_dest));
464 if (cur_dest == NULL)
468 cur_dest->str = strdup(cur_src->str);
469 cur_src = cur_src->next;
472 dest->last = cur_dest;
477 /*********************************************************************
479 * Function : list_append_list_unique
481 * Description : Append a string list to another list.
482 * Duplicate items are not added.
485 * 1 : dest = pointer to destination for merge. Caller allocs.
486 * 2 : src = pointer to source for merge.
490 *********************************************************************/
491 void list_append_list_unique(struct list *dest, const struct list *src)
493 struct list * cur = src->next;
497 enlist_unique(dest, cur->str, 0);
503 /*********************************************************************
507 * Description : Add a mapping from given name to given value to a
510 * Note: Since all strings will be free()d in free_map()
511 * later, use the copy flags for constants or
512 * strings that will be independantly free()d.
515 * 1 : the_map = map to add to
516 * 2 : name = name to add
517 * 3 : nc = flag set if a copy of name should be used
518 * 4 : value = value to add
519 * 5 : vc = flag set if a copy of value should be used
523 *********************************************************************/
524 void map(struct map *the_map, const char *name, int nc, const char *value, int vc)
526 struct map_entry *new_entry;
528 if (NULL == (new_entry = zalloc(sizeof(*new_entry))))
533 new_entry->name = nc ? strdup(name) : name;
534 new_entry->value = vc ? strdup(value) : value;
535 /* new_entry->next = NULL; - implied by zalloc */
539 the_map->last = the_map->last->next = new_entry;
543 the_map->last = the_map->first = new_entry;
549 /*********************************************************************
553 * Description : Look up an item with a given name in a map, and
557 * 1 : name = name parameter to look for
559 * Returns : the value if found, else the empty string
561 *********************************************************************/
562 const char *lookup(const struct map *the_map, const char *name)
564 const struct map_entry *cur_entry = the_map->first;
568 if (!strcmp(name, cur_entry->name))
570 return cur_entry->value;
572 cur_entry = cur_entry->next;
578 /*********************************************************************
582 * Description : Create a new, empty map.
586 * Returns : A new, empty map, or NULL if out of memory.
588 *********************************************************************/
589 struct map *new_map(void)
591 return (struct map *) zalloc(sizeof(struct map));
595 /*********************************************************************
597 * Function : free_map
599 * Description : Free the memory occupied by a map and its
603 * 1 : cur_entry = map to be freed. May be NULL.
607 *********************************************************************/
608 void free_map(struct map *the_map)
610 struct map_entry *cur_entry;
611 struct map_entry *next_entry;
618 for (cur_entry = the_map->first; cur_entry != NULL; cur_entry = next_entry)
620 freez((char *)cur_entry->name);
621 freez((char *)cur_entry->value);
623 next_entry = cur_entry->next;
627 the_map->first = the_map->last = NULL;