Initial revision
[cacao.git] / toolbox / chain.c
1 /************************* toolbox/chain.c *************************************
2
3         Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
4
5         See file COPYRIGHT for information on usage and disclaimer of warranties
6
7         Not documented, see chain.h.
8
9         Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
10
11         Last Change: 1996/10/03
12
13 *******************************************************************************/
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <assert.h>
18
19 #include "memory.h"
20 #include "chain.h"
21
22
23
24 chain *chain_new ()
25 {
26         chain *c;
27         
28         c = NEW (chain);
29         c -> usedump = 0;
30         c -> first = NULL;
31         c -> last = NULL;
32         c -> active = NULL;
33
34         return c;
35 }
36
37 chain *chain_dnew ()
38 {
39         chain *c;
40         
41         c = DNEW (chain);
42         c -> usedump = 1;
43         c -> first = NULL;
44         c -> last = NULL;
45         c -> active = NULL;
46
47         return c;
48 }
49
50
51 void chain_free (chain *c)
52 {
53         chainlink *l;
54
55         assert (! c->usedump);
56
57         l = c->first;
58         while (l) {
59                 chainlink *nextl = l->next;
60                 
61                 FREE (l, chainlink);
62                 l = nextl;      
63                 }
64         
65         FREE (c, chain);
66 }
67
68
69 void chain_addafter(chain *c, void *element)
70 {
71         chainlink *active,*newlink;
72
73     active = c->active;
74
75         if (c -> usedump) newlink = DNEW (chainlink);
76         else              newlink = NEW (chainlink);
77
78         newlink -> element = element;
79         
80         if (active) {
81                 newlink -> next = active -> next;
82                 newlink -> prev = active;
83                 
84                 active -> next = newlink;
85                 if (newlink -> next) newlink -> next -> prev = newlink;
86                                 else c -> last = newlink;
87                 }
88         else {  
89                 newlink -> next = NULL;
90                 newlink -> prev = NULL;
91
92                 c -> active = newlink;  
93                 c -> first = newlink;
94                 c -> last = newlink;
95                 }
96 }
97
98
99 void chain_addbefore(chain *c, void *element)
100 {
101         chainlink *active,*newlink;
102
103     active = c->active;
104
105         if (c -> usedump) newlink = DNEW (chainlink);
106         else              newlink = NEW (chainlink);
107         
108         newlink -> element = element;
109         
110         if (active) {
111                 newlink -> next = active;
112                 newlink -> prev = active -> prev;
113                 
114                 active -> prev = newlink;
115                 if (newlink -> prev) newlink -> prev -> next = newlink;
116                 else                 c -> first = newlink;
117                 }
118         else {  
119                 newlink -> next = NULL;
120                 newlink -> prev = NULL;
121
122                 c -> active = newlink;  
123                 c -> first = newlink;
124                 c -> last = newlink;
125                 }
126 }
127
128 void chain_addlast (chain *c, void *e)
129 {
130         chain_last (c);
131         chain_addafter (c, e);
132 }
133
134 void chain_addfirst (chain *c, void *e)
135 {
136         chain_first (c);
137         chain_addbefore (c, e);
138 }
139
140
141 void chain_remove (chain *c)
142 {
143         chainlink *active;
144         
145         active = c -> active;
146         assert (active);
147
148         if (active -> next) {
149                 active -> next -> prev = active -> prev;
150                 }
151         else {
152                 c -> last = active -> prev;
153                 }
154         
155         if (active -> prev) {
156                 active -> prev -> next = active -> next;
157                 }
158         else {
159                 c -> first = active -> next;
160                 }
161
162
163         if (active->prev) 
164                 c -> active = active->prev;
165         else
166                 c -> active = active->next;
167
168         if (! c -> usedump) FREE (active, chainlink);
169 }
170
171
172 void *chain_remove_go_prev (chain *c)
173 {
174         chain_remove (c);
175         return chain_this (c);
176 }
177
178
179
180 void chain_removespecific(chain *c, void *e)
181 {
182         void *ce;
183         
184         ce = chain_first (c);
185         while (ce) {
186                 if (e == ce) { chain_remove (c); return; }
187         ce = chain_next (c);            
188                 }
189                 
190 }
191
192 void *chain_next(chain *c)
193 {
194         chainlink *active;
195         
196         active = c -> active;
197         if (!active) return NULL;
198         
199         if (active -> next) {
200                 c -> active = active -> next;
201                 return c -> active -> element;
202                 }
203                 
204         return NULL;
205 }
206
207 void *chain_prev(chain *c)
208 {
209         chainlink *active;
210         
211         active = c -> active;
212         if (!active) return NULL;
213         
214         if (active -> prev) {
215                 c -> active = active -> prev;
216                 return c -> active -> element;
217                 }
218
219         return NULL;
220 }
221
222
223 void *chain_this(chain *c)
224 {
225         if (c -> active) return c -> active -> element;
226         return NULL;
227 }
228
229
230 void *chain_first(chain *c)
231 {
232         c -> active = c -> first;
233         if (c -> active) return c -> active -> element;
234         return NULL;
235 }
236
237 void *chain_last(chain *c)
238 {
239         c -> active = c -> last;
240         if (c -> active) return c -> active -> element;;
241         return NULL;
242 }
243