1/***************************************************************************
2 *                                  _   _ ____  _
3 *  Project                     ___| | | |  _ \| |
4 *                             / __| | | | |_) | |
5 *                            | (__| |_| |  _ <| |___
6 *                             \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at http://curl.haxx.se/docs/copyright.html.
13 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ***************************************************************************/
22
23#include "setup.h"
24
25#include <stdio.h>
26#include <stdarg.h>
27#include <stdlib.h>
28
29#include <string.h>
30#include "curl_memory.h"
31#include "slist.h"
32
33/* The last #include file should be: */
34#include "memdebug.h"
35
36/* returns last node in linked list */
37static struct curl_slist *slist_get_last(struct curl_slist *list)
38{
39  struct curl_slist     *item;
40
41  /* if caller passed us a NULL, return now */
42  if(!list)
43    return NULL;
44
45  /* loop through to find the last item */
46  item = list;
47  while(item->next) {
48    item = item->next;
49  }
50  return item;
51}
52
53/*
54 * curl_slist_append() appends a string to the linked list. It always returns
55 * the address of the first record, so that you can use this function as an
56 * initialization function as well as an append function. If you find this
57 * bothersome, then simply create a separate _init function and call it
58 * appropriately from within the program.
59 */
60struct curl_slist *curl_slist_append(struct curl_slist *list,
61                                     const char *data)
62{
63  struct curl_slist     *last;
64  struct curl_slist     *new_item;
65
66  new_item = malloc(sizeof(struct curl_slist));
67  if(new_item) {
68    char *dupdata = strdup(data);
69    if(dupdata) {
70      new_item->next = NULL;
71      new_item->data = dupdata;
72    }
73    else {
74      free(new_item);
75      return NULL;
76    }
77  }
78  else
79    return NULL;
80
81  if(list) {
82    last = slist_get_last(list);
83    last->next = new_item;
84    return list;
85  }
86
87  /* if this is the first item, then new_item *is* the list */
88  return new_item;
89}
90
91/*
92 * Curl_slist_duplicate() duplicates a linked list. It always returns the
93 * address of the first record of the cloned list or NULL in case of an
94 * error (or if the input list was NULL).
95 */
96struct curl_slist *Curl_slist_duplicate(struct curl_slist *inlist)
97{
98  struct curl_slist *outlist = NULL;
99  struct curl_slist *tmp;
100
101  while(inlist) {
102    tmp = curl_slist_append(outlist, inlist->data);
103
104    if(!tmp) {
105      curl_slist_free_all(outlist);
106      return NULL;
107    }
108
109    outlist = tmp;
110    inlist = inlist->next;
111  }
112  return outlist;
113}
114
115/* be nice and clean up resources */
116void curl_slist_free_all(struct curl_slist *list)
117{
118  struct curl_slist     *next;
119  struct curl_slist     *item;
120
121  if(!list)
122    return;
123
124  item = list;
125  do {
126    next = item->next;
127
128    if(item->data) {
129      free(item->data);
130    }
131    free(item);
132    item = next;
133  } while(next);
134}
135
136