]> git.proxmox.com Git - spiceterm.git/blob - ring.h
implement scroll
[spiceterm.git] / ring.h
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