1/***************************************************************************
2 *                                  _   _ ____  _
3 *  Project                     ___| | | |  _ \| |
4 *                             / __| | | | |_) | |
5 *                            | (__| |_| |  _ <| |___
6 *                             \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2013, 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 "curl_setup.h"
24
25#include "slist.h"
26
27/* The last #include files should be: */
28#include "curl_memory.h"
29#include "memdebug.h"
30
31/* returns last node in linked list */
32static struct curl_slist *slist_get_last(struct curl_slist *list)
33{
34  struct curl_slist     *item;
35
36  /* if caller passed us a NULL, return now */
37  if(!list)
38    return NULL;
39
40  /* loop through to find the last item */
41  item = list;
42  while(item->next) {
43    item = item->next;
44  }
45  return item;
46}
47
48/*
49 * Curl_slist_append_nodup() appends a string to the linked list. Rather than
50 * copying the string in dynamic storage, it takes its ownership. The string
51 * should have been malloc()ated. Curl_slist_append_nodup always returns
52 * the address of the first record, so that you can use this function as an
53 * initialization function as well as an append function.
54 * If an error occurs, NULL is returned and the string argument is NOT
55 * released.
56 */
57struct curl_slist *Curl_slist_append_nodup(struct curl_slist *list, char *data)
58{
59  struct curl_slist     *last;
60  struct curl_slist     *new_item;
61
62  DEBUGASSERT(data);
63
64  new_item = malloc(sizeof(struct curl_slist));
65  if(!new_item)
66    return NULL;
67
68  new_item->next = NULL;
69  new_item->data = data;
70
71  /* if this is the first item, then new_item *is* the list */
72  if(!list)
73    return new_item;
74
75  last = slist_get_last(list);
76  last->next = new_item;
77  return list;
78}
79
80/*
81 * curl_slist_append() appends a string to the linked list. It always returns
82 * the address of the first record, so that you can use this function as an
83 * initialization function as well as an append function. If you find this
84 * bothersome, then simply create a separate _init function and call it
85 * appropriately from within the program.
86 */
87struct curl_slist *curl_slist_append(struct curl_slist *list,
88                                     const char *data)
89{
90  char *dupdata = strdup(data);
91
92  if(!dupdata)
93    return NULL;
94
95  list = Curl_slist_append_nodup(list, dupdata);
96  if(!list)
97    free(dupdata);
98
99  return list;
100}
101
102/*
103 * Curl_slist_duplicate() duplicates a linked list. It always returns the
104 * address of the first record of the cloned list or NULL in case of an
105 * error (or if the input list was NULL).
106 */
107struct curl_slist *Curl_slist_duplicate(struct curl_slist *inlist)
108{
109  struct curl_slist *outlist = NULL;
110  struct curl_slist *tmp;
111
112  while(inlist) {
113    tmp = curl_slist_append(outlist, inlist->data);
114
115    if(!tmp) {
116      curl_slist_free_all(outlist);
117      return NULL;
118    }
119
120    outlist = tmp;
121    inlist = inlist->next;
122  }
123  return outlist;
124}
125
126/* be nice and clean up resources */
127void curl_slist_free_all(struct curl_slist *list)
128{
129  struct curl_slist     *next;
130  struct curl_slist     *item;
131
132  if(!list)
133    return;
134
135  item = list;
136  do {
137    next = item->next;
138    Curl_safefree(item->data);
139    free(item);
140    item = next;
141  } while(next);
142}
143
144