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