Coverage Report

Created: 2025-02-07 06:04

/src/clib/deps/list/list.c
Line
Count
Source (jump to first uncovered line)
1
2
//
3
// list.c
4
//
5
// Copyright (c) 2010 TJ Holowaychuk <tj@vision-media.ca>
6
//
7
8
#include "list.h"
9
10
/*
11
 * Allocate a new list_t. NULL on failure.
12
 */
13
14
list_t *
15
259
list_new(void) {
16
259
  list_t *self;
17
259
  if (!(self = LIST_MALLOC(sizeof(list_t))))
18
0
    return NULL;
19
259
  self->head = NULL;
20
259
  self->tail = NULL;
21
259
  self->free = NULL;
22
259
  self->match = NULL;
23
259
  self->len = 0;
24
259
  return self;
25
259
}
26
27
/*
28
 * Free the list.
29
 */
30
31
void
32
259
list_destroy(list_t *self) {
33
259
  unsigned int len = self->len;
34
259
  list_node_t *next;
35
259
  list_node_t *curr = self->head;
36
37
232k
  while (len--) {
38
232k
    next = curr->next;
39
232k
    if (self->free) self->free(curr->val);
40
232k
    LIST_FREE(curr);
41
232k
    curr = next;
42
232k
  }
43
44
259
  LIST_FREE(self);
45
259
}
46
47
/*
48
 * Append the given node to the list
49
 * and return the node, NULL on failure.
50
 */
51
52
list_node_t *
53
232k
list_rpush(list_t *self, list_node_t *node) {
54
232k
  if (!node) return NULL;
55
56
232k
  if (self->len) {
57
232k
    node->prev = self->tail;
58
232k
    node->next = NULL;
59
232k
    self->tail->next = node;
60
232k
    self->tail = node;
61
232k
  } else {
62
211
    self->head = self->tail = node;
63
211
    node->prev = node->next = NULL;
64
211
  }
65
66
232k
  ++self->len;
67
232k
  return node;
68
232k
}
69
70
/*
71
 * Return / detach the last node in the list, or NULL.
72
 */
73
74
list_node_t *
75
0
list_rpop(list_t *self) {
76
0
  if (!self->len) return NULL;
77
78
0
  list_node_t *node = self->tail;
79
80
0
  if (--self->len) {
81
0
    (self->tail = node->prev)->next = NULL;
82
0
  } else {
83
0
    self->tail = self->head = NULL;
84
0
  }
85
86
0
  node->next = node->prev = NULL;
87
0
  return node;
88
0
}
89
90
/*
91
 * Return / detach the first node in the list, or NULL.
92
 */
93
94
list_node_t *
95
0
list_lpop(list_t *self) {
96
0
  if (!self->len) return NULL;
97
98
0
  list_node_t *node = self->head;
99
100
0
  if (--self->len) {
101
0
    (self->head = node->next)->prev = NULL;
102
0
  } else {
103
0
    self->head = self->tail = NULL;
104
0
  }
105
106
0
  node->next = node->prev = NULL;
107
0
  return node;
108
0
}
109
110
/*
111
 * Prepend the given node to the list
112
 * and return the node, NULL on failure.
113
 */
114
115
list_node_t *
116
0
list_lpush(list_t *self, list_node_t *node) {
117
0
  if (!node) return NULL;
118
119
0
  if (self->len) {
120
0
    node->next = self->head;
121
0
    node->prev = NULL;
122
0
    self->head->prev = node;
123
0
    self->head = node;
124
0
  } else {
125
0
    self->head = self->tail = node;
126
0
    node->prev = node->next = NULL;
127
0
  }
128
129
0
  ++self->len;
130
0
  return node;
131
0
}
132
133
/*
134
 * Return the node associated to val or NULL.
135
 */
136
137
list_node_t *
138
0
list_find(list_t *self, void *val) {
139
0
  list_iterator_t *it = list_iterator_new(self, LIST_HEAD);
140
0
  list_node_t *node;
141
142
0
  while ((node = list_iterator_next(it))) {
143
0
    if (self->match) {
144
0
      if (self->match(val, node->val)) {
145
0
        list_iterator_destroy(it);
146
0
        return node;
147
0
      }
148
0
    } else {
149
0
      if (val == node->val) {
150
0
        list_iterator_destroy(it);
151
0
        return node;
152
0
      }
153
0
    }
154
0
  }
155
156
0
  list_iterator_destroy(it);
157
0
  return NULL;
158
0
}
159
160
/*
161
 * Return the node at the given index or NULL.
162
 */
163
164
list_node_t *
165
0
list_at(list_t *self, int index) {
166
0
  list_direction_t direction = LIST_HEAD;
167
168
0
  if (index < 0) {
169
0
    direction = LIST_TAIL;
170
0
    index = ~index;
171
0
  }
172
173
0
  if ((unsigned)index < self->len) {
174
0
    list_iterator_t *it = list_iterator_new(self, direction);
175
0
    list_node_t *node = list_iterator_next(it);
176
0
    while (index--) node = list_iterator_next(it);
177
0
    list_iterator_destroy(it);
178
0
    return node;
179
0
  }
180
181
0
  return NULL;
182
0
}
183
184
/*
185
 * Remove the given node from the list, freeing it and it's value.
186
 */
187
188
void
189
0
list_remove(list_t *self, list_node_t *node) {
190
0
  node->prev
191
0
    ? (node->prev->next = node->next)
192
0
    : (self->head = node->next);
193
194
0
  node->next
195
0
    ? (node->next->prev = node->prev)
196
0
    : (self->tail = node->prev);
197
198
0
  if (self->free) self->free(node->val);
199
200
0
  LIST_FREE(node);
201
0
  --self->len;
202
0
}