1
1
/* Singly-linked list
2
2
* – Two sentinel nodes (head and tail) eliminate edge-case tests.
3
3
* – The list stores generic data pointers ('void *').
4
- * – All primitives are defined ` static inline` so they can live entirely
4
+ * – All primitives are defined ' static inline' so they can live entirely
5
5
* in the header without multiple-definition issues.
6
- * – Comments follow C style and use concise American English.
7
6
*/
8
7
9
8
#pragma once
10
9
11
10
#include <lib/libc.h>
12
11
#include <lib/malloc.h>
13
12
13
+ #include "private/utils.h"
14
+
14
15
/* List node */
15
16
typedef struct list_node {
16
17
struct list_node * next ;
@@ -26,12 +27,18 @@ typedef struct {
26
27
27
28
static inline list_t * list_create (void )
28
29
{
29
- list_t * list = malloc (sizeof (list_t ));
30
- list_node_t * head = malloc (sizeof (list_node_t ));
31
- list_node_t * tail = malloc (sizeof (list_node_t ));
30
+ list_t * list = malloc (sizeof (* list ));
31
+ if (unlikely (!list ))
32
+ return NULL ;
33
+
34
+ list_node_t * head = malloc (sizeof (* head ));
35
+ if (unlikely (!head )) {
36
+ free (list );
37
+ return NULL ;
38
+ }
32
39
33
- if (! list || ! head || ! tail ) { /* cleanup on failure */
34
- free ( tail );
40
+ list_node_t * tail = malloc ( sizeof ( * tail ));
41
+ if ( unlikely (! tail )) {
35
42
free (head );
36
43
free (list );
37
44
return NULL ;
@@ -64,7 +71,7 @@ static inline list_node_t *list_next(const list_node_t *node)
64
71
static inline list_node_t * list_cnext (const list_t * list ,
65
72
const list_node_t * node )
66
73
{
67
- if (!list || !node )
74
+ if (unlikely ( !list || !node ) )
68
75
return NULL ;
69
76
return (node -> next == list -> tail ) ? list -> head -> next : node -> next ;
70
77
}
@@ -73,17 +80,15 @@ static inline list_node_t *list_cnext(const list_t *list,
73
80
74
81
static inline list_node_t * list_pushback (list_t * list , void * data )
75
82
{
76
- if (!list )
83
+ if (unlikely ( !list ) )
77
84
return NULL ;
78
85
79
- list_node_t * node = malloc (sizeof (list_node_t ));
80
- if (!node )
86
+ list_node_t * node = malloc (sizeof (* node ));
87
+ if (unlikely ( !node ) )
81
88
return NULL ;
82
89
83
90
node -> data = data ;
84
91
node -> next = list -> tail ;
85
- list -> tail -> data = NULL ; /* head and tail sentinels never hold data */
86
- list -> head -> data = NULL ;
87
92
88
93
/* Insert before tail sentinel */
89
94
list_node_t * prev = list -> head ;
@@ -97,7 +102,7 @@ static inline list_node_t *list_pushback(list_t *list, void *data)
97
102
98
103
static inline void * list_pop (list_t * list )
99
104
{
100
- if (list_is_empty (list ))
105
+ if (unlikely ( list_is_empty (list ) ))
101
106
return NULL ;
102
107
103
108
list_node_t * first = list -> head -> next ;
@@ -112,14 +117,14 @@ static inline void *list_pop(list_t *list)
112
117
/* Remove a specific node; returns its data */
113
118
static inline void * list_remove (list_t * list , list_node_t * target )
114
119
{
115
- if (!list || !target || list_is_empty (list ))
120
+ if (unlikely ( !list || !target || list_is_empty (list ) ))
116
121
return NULL ;
117
122
118
123
list_node_t * prev = list -> head ;
119
124
while (prev -> next != list -> tail && prev -> next != target )
120
125
prev = prev -> next ;
121
126
122
- if (prev -> next != target )
127
+ if (unlikely ( prev -> next != target ) )
123
128
return NULL ; /* node not found */
124
129
125
130
prev -> next = target -> next ;
@@ -137,15 +142,16 @@ static inline list_node_t *list_foreach(list_t *list,
137
142
void * ),
138
143
void * arg )
139
144
{
140
- if (!list || !cb )
145
+ if (unlikely ( !list || !cb ) )
141
146
return NULL ;
142
147
143
148
list_node_t * node = list -> head -> next ;
144
149
while (node != list -> tail ) {
150
+ list_node_t * next = node -> next ; /* Save next before callback */
145
151
list_node_t * res = cb (node , arg );
146
152
if (res )
147
153
return res ;
148
- node = node -> next ;
154
+ node = next ;
149
155
}
150
156
return NULL ;
151
157
}
@@ -154,7 +160,7 @@ static inline list_node_t *list_foreach(list_t *list,
154
160
155
161
static inline void list_clear (list_t * list )
156
162
{
157
- if (!list )
163
+ if (unlikely ( !list ) )
158
164
return ;
159
165
while (!list_is_empty (list ))
160
166
list_pop (list );
0 commit comments