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 */ 34static void 35llist_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 43struct curl_llist * 44Curl_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 */ 68int 69Curl_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 */ 109int 110Curl_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 144void 145Curl_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 155size_t 156Curl_llist_count(struct curl_llist *list) 157{ 158 return list->size; 159} 160 161/* 162 * @unittest: 1300 163 */ 164int 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