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