]>
Commit | Line | Data |
---|---|---|
cc04455b DM |
1 | /* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ |
2 | /* | |
3 | Copyright (C) 2009 Red Hat, Inc. | |
4 | ||
5 | This library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Lesser General Public | |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
9 | ||
10 | This library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Lesser General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
16 | License along with this library; if not, see <http://www.gnu.org/licenses/>. | |
17 | */ | |
18 | ||
19 | #ifndef _H_RING2 | |
20 | #define _H_RING2 | |
21 | ||
22 | #include <glib.h> | |
23 | #include <spice/macros.h> | |
24 | //#include "spice_common.h" | |
25 | ||
26 | SPICE_BEGIN_DECLS | |
27 | ||
28 | typedef struct Ring RingItem; | |
29 | typedef struct Ring { | |
30 | RingItem *prev; | |
31 | RingItem *next; | |
32 | } Ring; | |
33 | ||
34 | static inline void ring_init(Ring *ring) | |
35 | { | |
36 | ring->next = ring->prev = ring; | |
37 | } | |
38 | ||
39 | static inline void ring_item_init(RingItem *item) | |
40 | { | |
41 | item->next = item->prev = NULL; | |
42 | } | |
43 | ||
44 | static inline int ring_item_is_linked(RingItem *item) | |
45 | { | |
46 | return !!item->next; | |
47 | } | |
48 | ||
49 | static inline int ring_is_empty(Ring *ring) | |
50 | { | |
51 | g_assert(ring->next != NULL && ring->prev != NULL); | |
52 | return ring == ring->next; | |
53 | } | |
54 | ||
55 | static inline void ring_add(Ring *ring, RingItem *item) | |
56 | { | |
57 | g_assert(ring->next != NULL && ring->prev != NULL); | |
58 | g_assert(item->next == NULL && item->prev == NULL); | |
59 | ||
60 | item->next = ring->next; | |
61 | item->prev = ring; | |
62 | ring->next = item->next->prev = item; | |
63 | } | |
64 | ||
65 | static inline void ring_add_after(RingItem *item, RingItem *pos) | |
66 | { | |
67 | ring_add(pos, item); | |
68 | } | |
69 | ||
70 | static inline void ring_add_before(RingItem *item, RingItem *pos) | |
71 | { | |
72 | ring_add(pos->prev, item); | |
73 | } | |
74 | ||
75 | static inline void __ring_remove(RingItem *item) | |
76 | { | |
77 | item->next->prev = item->prev; | |
78 | item->prev->next = item->next; | |
79 | item->prev = item->next = 0; | |
80 | } | |
81 | ||
82 | static inline void ring_remove(RingItem *item) | |
83 | { | |
84 | g_assert(item->next != NULL && item->prev != NULL); | |
85 | g_assert(item->next != item); | |
86 | ||
87 | __ring_remove(item); | |
88 | } | |
89 | ||
90 | static inline RingItem *ring_get_head(Ring *ring) | |
91 | { | |
92 | RingItem *ret; | |
93 | ||
94 | g_assert(ring->next != NULL && ring->prev != NULL); | |
95 | ||
96 | if (ring_is_empty(ring)) { | |
97 | return NULL; | |
98 | } | |
99 | ret = ring->next; | |
100 | return ret; | |
101 | } | |
102 | ||
103 | static inline RingItem *ring_get_tail(Ring *ring) | |
104 | { | |
105 | RingItem *ret; | |
106 | ||
107 | g_assert(ring->next != NULL && ring->prev != NULL); | |
108 | ||
109 | if (ring_is_empty(ring)) { | |
110 | return NULL; | |
111 | } | |
112 | ret = ring->prev; | |
113 | return ret; | |
114 | } | |
115 | ||
116 | static inline RingItem *ring_next(Ring *ring, RingItem *pos) | |
117 | { | |
118 | RingItem *ret; | |
119 | ||
120 | g_assert(ring->next != NULL && ring->prev != NULL); | |
121 | g_assert(pos); | |
122 | g_assert(pos->next != NULL && pos->prev != NULL); | |
123 | ret = pos->next; | |
124 | return (ret == ring) ? NULL : ret; | |
125 | } | |
126 | ||
127 | static inline RingItem *ring_prev(Ring *ring, RingItem *pos) | |
128 | { | |
129 | RingItem *ret; | |
130 | ||
131 | g_assert(ring->next != NULL && ring->prev != NULL); | |
132 | g_assert(pos); | |
133 | g_assert(pos->next != NULL && pos->prev != NULL); | |
134 | ret = pos->prev; | |
135 | return (ret == ring) ? NULL : ret; | |
136 | } | |
137 | ||
138 | #define RING_FOREACH_SAFE(var, next, ring) \ | |
139 | for ((var) = ring_get_head(ring); \ | |
140 | (var) && ((next) = ring_next(ring, (var)), 1); \ | |
141 | (var) = (next)) | |
142 | ||
143 | ||
144 | #define RING_FOREACH(var, ring) \ | |
145 | for ((var) = ring_get_head(ring); \ | |
146 | (var); \ | |
147 | (var) = ring_next(ring, var)) | |
148 | ||
149 | #define RING_FOREACH_REVERSED(var, ring) \ | |
150 | for ((var) = ring_get_tail(ring); \ | |
151 | (var); \ | |
152 | (var) = ring_prev(ring, var)) | |
153 | ||
154 | ||
155 | static inline unsigned int ring_get_length(Ring *ring) | |
156 | { | |
157 | RingItem *i; | |
158 | unsigned int ret = 0; | |
159 | ||
160 | for (i = ring_get_head(ring); | |
161 | i != NULL; | |
162 | i = ring_next(ring, i)) | |
163 | ret++; | |
164 | ||
165 | return ret; | |
166 | } | |
167 | ||
168 | SPICE_END_DECLS | |
169 | ||
170 | #endif |