xref: /third_party/curl/lib/llist.c (revision 13498266)
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