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 "curl_setup.h"
24 
25 #include "llist.h"
26 #include "curl_memory.h"
27 
28 /* this must be the last include file */
29 #include "memdebug.h"
30 
31 /*
32  * @unittest: 1300
33  */
34 static void
llist_init(struct curl_llist * l,curl_llist_dtor dtor)35 llist_init(struct curl_llist *l, curl_llist_dtor dtor)
36 {
37   l->size = 0;
38   l->dtor = dtor;
39   l->head = NULL;
40   l->tail = NULL;
41 }
42 
43 struct curl_llist *
Curl_llist_alloc(curl_llist_dtor dtor)44 Curl_llist_alloc(curl_llist_dtor dtor)
45 {
46   struct curl_llist *list;
47 
48   list = malloc(sizeof(struct curl_llist));
49   if(!list)
50     return NULL;
51 
52   llist_init(list, dtor);
53 
54   return list;
55 }
56 
57 /*
58  * Curl_llist_insert_next()
59  *
60  * Inserts a new list element after the given one 'e'. If the given existing
61  * entry is NULL and the list already has elements, the new one will be
62  * inserted first in the list.
63  *
64  * Returns: 1 on success and 0 on failure.
65  *
66  * @unittest: 1300
67  */
68 int
Curl_llist_insert_next(struct curl_llist * list,struct curl_llist_element * e,const void * p)69 Curl_llist_insert_next(struct curl_llist *list, struct curl_llist_element *e,
70                        const void *p)
71 {
72   struct curl_llist_element *ne = malloc(sizeof(struct curl_llist_element));
73   if(!ne)
74     return 0;
75 
76   ne->ptr = (void *) p;
77   if(list->size == 0) {
78     list->head = ne;
79     list->head->prev = NULL;
80     list->head->next = NULL;
81     list->tail = ne;
82   }
83   else {
84     /* if 'e' is NULL here, we insert the new element first in the list */
85     ne->next = e?e->next:list->head;
86     ne->prev = e;
87     if(!e) {
88       list->head->prev = ne;
89       list->head = ne;
90     }
91     else if(e->next) {
92       e->next->prev = ne;
93     }
94     else {
95       list->tail = ne;
96     }
97     if(e)
98       e->next = ne;
99   }
100 
101   ++list->size;
102 
103   return 1;
104 }
105 
106 /*
107  * @unittest: 1300
108  */
109 int
Curl_llist_remove(struct curl_llist * list,struct curl_llist_element * e,void * user)110 Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e,
111                   void *user)
112 {
113   if(e == NULL || list->size == 0)
114     return 1;
115 
116   if(e == list->head) {
117     list->head = e->next;
118 
119     if(list->head == NULL)
120       list->tail = NULL;
121     else
122       e->next->prev = NULL;
123   }
124   else {
125     e->prev->next = e->next;
126     if(!e->next)
127       list->tail = e->prev;
128     else
129       e->next->prev = e->prev;
130   }
131 
132   list->dtor(user, e->ptr);
133 
134   e->ptr  = NULL;
135   e->prev = NULL;
136   e->next = NULL;
137 
138   free(e);
139   --list->size;
140 
141   return 1;
142 }
143 
144 void
Curl_llist_destroy(struct curl_llist * list,void * user)145 Curl_llist_destroy(struct curl_llist *list, void *user)
146 {
147   if(list) {
148     while(list->size > 0)
149       Curl_llist_remove(list, list->tail, user);
150 
151     free(list);
152   }
153 }
154 
155 size_t
Curl_llist_count(struct curl_llist * list)156 Curl_llist_count(struct curl_llist *list)
157 {
158   return list->size;
159 }
160 
161 /*
162  * @unittest: 1300
163  */
Curl_llist_move(struct curl_llist * list,struct curl_llist_element * e,struct curl_llist * to_list,struct curl_llist_element * to_e)164 int Curl_llist_move(struct curl_llist *list, struct curl_llist_element *e,
165                     struct curl_llist *to_list,
166                     struct curl_llist_element *to_e)
167 {
168   /* Remove element from list */
169   if(e == NULL || list->size == 0)
170     return 0;
171 
172   if(e == list->head) {
173     list->head = e->next;
174 
175     if(list->head == NULL)
176       list->tail = NULL;
177     else
178       e->next->prev = NULL;
179   }
180   else {
181     e->prev->next = e->next;
182     if(!e->next)
183       list->tail = e->prev;
184     else
185       e->next->prev = e->prev;
186   }
187 
188   --list->size;
189 
190   /* Add element to to_list after to_e */
191   if(to_list->size == 0) {
192     to_list->head = e;
193     to_list->head->prev = NULL;
194     to_list->head->next = NULL;
195     to_list->tail = e;
196   }
197   else {
198     e->next = to_e->next;
199     e->prev = to_e;
200     if(to_e->next) {
201       to_e->next->prev = e;
202     }
203     else {
204       to_list->tail = e;
205     }
206     to_e->next = e;
207   }
208 
209   ++to_list->size;
210 
211   return 1;
212 }
213