1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 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.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 * SPDX-License-Identifier: curl 22 * 23 ***************************************************************************/ 24 25#include "curl_setup.h" 26 27#include <curl/curl.h> 28 29#include "llist.h" 30#include "curl_memory.h" 31 32/* this must be the last include file */ 33#include "memdebug.h" 34 35/* 36 * @unittest: 1300 37 */ 38void 39Curl_llist_init(struct Curl_llist *l, Curl_llist_dtor dtor) 40{ 41 l->size = 0; 42 l->dtor = dtor; 43 l->head = NULL; 44 l->tail = NULL; 45} 46 47/* 48 * Curl_llist_insert_next() 49 * 50 * Inserts a new list element after the given one 'e'. If the given existing 51 * entry is NULL and the list already has elements, the new one will be 52 * inserted first in the list. 53 * 54 * The 'ne' argument should be a pointer into the object to store. 55 * 56 * @unittest: 1300 57 */ 58void 59Curl_llist_insert_next(struct Curl_llist *list, struct Curl_llist_element *e, 60 const void *p, 61 struct Curl_llist_element *ne) 62{ 63 ne->ptr = (void *) p; 64 if(list->size == 0) { 65 list->head = ne; 66 list->head->prev = NULL; 67 list->head->next = NULL; 68 list->tail = ne; 69 } 70 else { 71 /* if 'e' is NULL here, we insert the new element first in the list */ 72 ne->next = e?e->next:list->head; 73 ne->prev = e; 74 if(!e) { 75 list->head->prev = ne; 76 list->head = ne; 77 } 78 else if(e->next) { 79 e->next->prev = ne; 80 } 81 else { 82 list->tail = ne; 83 } 84 if(e) 85 e->next = ne; 86 } 87 88 ++list->size; 89} 90 91/* 92 * @unittest: 1300 93 */ 94void 95Curl_llist_remove(struct Curl_llist *list, struct Curl_llist_element *e, 96 void *user) 97{ 98 void *ptr; 99 if(!e || list->size == 0) 100 return; 101 102 if(e == list->head) { 103 list->head = e->next; 104 105 if(!list->head) 106 list->tail = NULL; 107 else 108 e->next->prev = NULL; 109 } 110 else { 111 if(e->prev) 112 e->prev->next = e->next; 113 114 if(!e->next) 115 list->tail = e->prev; 116 else 117 e->next->prev = e->prev; 118 } 119 120 ptr = e->ptr; 121 122 e->ptr = NULL; 123 e->prev = NULL; 124 e->next = NULL; 125 126 --list->size; 127 128 /* call the dtor() last for when it actually frees the 'e' memory itself */ 129 if(list->dtor) 130 list->dtor(user, ptr); 131} 132 133void 134Curl_llist_destroy(struct Curl_llist *list, void *user) 135{ 136 if(list) { 137 while(list->size > 0) 138 Curl_llist_remove(list, list->tail, user); 139 } 140} 141 142size_t 143Curl_llist_count(struct Curl_llist *list) 144{ 145 return list->size; 146} 147