-
Notifications
You must be signed in to change notification settings - Fork 0
/
dlist.h
121 lines (100 loc) · 2.96 KB
/
dlist.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Copyright (C) 2016, 2017 Alexey Khrabrov, Bogdan Simion
//
// Distributed under the terms of the GNU General Public License.
//
// This file is part of Assignment 3, CSC469, Fall 2017.
//
// This is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this file. If not, see <http://www.gnu.org/licenses/>.
#ifndef _DLIST_H_
#define _DLIST_H_
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
// Doubly-linked list structures and helper functions
typedef struct _dlist_entry {
union {
struct _dlist_entry *next;
struct _dlist_entry *head;
};
union {
struct _dlist_entry *prev;
struct _dlist_entry *tail;
};
} dlist_entry;
typedef dlist_entry dlist;
// Get address of a structure by address of its field; useful for embedding list entries in structures
#define container_of(ptr, type, member) \
({ \
const typeof(((type*)0)->member) *_mptr = (ptr); \
(type*)((char*)_mptr - offsetof(type, member)); \
}) \
static inline void dlist_init(dlist *list)
{
assert(list != NULL);
list->head = list->tail = list;
}
static inline bool dlist_is_empty(const dlist *list)
{
assert(list != NULL);
if (list->head == list) {
assert(list->tail == list->head);
return true;
}
assert(list->tail != list);
return false;
}
static inline void dlist_insert_after(dlist_entry *place, dlist_entry *entry)
{
assert(place != NULL);
assert(place->next != NULL);
assert(entry != NULL);
entry->next = place->next;
entry->prev = place;
place->next = entry;
entry->next->prev = entry;
}
static inline void dlist_insert_before(dlist_entry *place, dlist_entry *entry)
{
dlist_insert_after(place->prev, entry);
}
static inline void dlist_insert_head(dlist *list, dlist_entry *entry)
{
dlist_insert_after(list, entry);
}
static inline void dlist_insert_tail(dlist *list, dlist_entry *entry)
{
dlist_insert_before(list, entry);
}
static inline dlist_entry *dlist_remove_entry(dlist_entry *entry)
{
assert(entry != NULL);
assert(entry->next != NULL);
assert(entry->prev != NULL);
if (entry->next == entry) {
assert(entry->prev == entry);
return NULL;
}
entry->next->prev = entry->prev;
entry->prev->next = entry->next;
return entry;
}
static inline dlist_entry *dlist_remove_head(dlist *list)
{
return dlist_remove_entry(list->head);
}
static inline dlist_entry *dlist_remove_tail(dlist *list)
{
return dlist_remove_entry(list->tail);
}
#endif// _DLIST_H_