- changing MaxInstructions to 100 for cthulhain (crazy nut) =:)
[bbkeys.git] / src / LinkedList.cc
blobec42f613c575468699a3906c736e26e6766b6f4a
1 // LinkedList.cc for Blackbox - an X11 Window manager
2 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 // DEALINGS IN THE SOFTWARE.
22 // $Id$
24 // stupid macros needed to access some functions in version 2 of the GNU C
25 // library
26 #ifndef _GNU_SOURCE
27 #define _GNU_SOURCE
28 #endif // _GNU_SOURCE
30 #include "LinkedList.hh"
32 #ifdef HAVE_CONFIG_H
33 # include "../config.h"
34 #endif // HAVE_CONFIG_H
36 #ifdef HAVE_STDIO_H
37 # include <stdio.h>
38 #endif // HAVE_STDIO_H
41 __llist_iterator::__llist_iterator(__llist *l) {
42 // initialize the iterator...
43 list = l;
45 if (list) {
46 if (! list->iterators)
47 list->iterators = new __llist;
49 list->iterators->insert(this);
52 reset();
56 __llist_iterator::~__llist_iterator(void) {
57 if (list && list->iterators)
58 list->iterators->remove(this);
62 void *__llist_iterator::current(void) {
63 // return the current node data... if any
64 return ((node) ? node->getData() : 0);
68 void __llist_iterator::reset(void) {
69 // update the iterator's current node to the first node in the linked list
70 if (list)
71 node = list->_first;
75 const int __llist_iterator::set(const int index) {
76 // set the current node to index
77 if (list) {
78 if (index < list->elements && index >= 0 && list->_first) {
79 node = list->_first;
81 for (register int i = 0; i < index; i++)
82 node = node->getNext();
84 return 1;
88 node = (__llist_node *) 0;
89 return 0;
93 void __llist_iterator::operator++(void) {
94 // iterate to the next node in the list...
95 node = ((node) ? node->getNext() : 0);
99 void __llist_iterator::operator++(int) {
100 // iterate to the next node in the list...
101 node = ((node) ? node->getNext() : 0);
105 __llist::__llist(void *d) {
106 // initialize the linked list...
107 _first = (__llist_node *) 0;
108 _last = (__llist_node *) 0;
109 iterators = (__llist *) 0;
110 elements = 0;
112 if (d) insert(d);
116 __llist::~__llist(void) {
117 // remove all the items in the list...
118 for (register int i = 0, r = elements; i < r; i++)
119 remove(0);
121 if (iterators) {
122 __llist_node *n = iterators->_first;
124 while (n) {
125 ((__llist_iterator *) n->getData())->list = (__llist *) 0;
126 ((__llist_iterator *) n->getData())->node = (__llist_node *) 0;
128 n = n->getNext();
131 delete iterators;
136 const int __llist::insert(void *d, int index) {
137 // insert item into linked list at specified index...
139 if ((! _first) || (! _last)) {
140 // list is empty... insert the item as the first item, regardless of the
141 // index given
142 _first = new __llist_node;
143 _first->setData(d);
144 _first->setNext((__llist_node *) 0);
145 _last = _first;
146 } else {
147 if (index == 0) {
148 // if index is 0... prepend the data on the list
149 __llist_node *nnode = new __llist_node;
151 nnode->setData(d);
152 nnode->setNext(_first);
154 _first = nnode;
155 } else if ((index == -1) || (index == elements)) {
156 // if index is -1... append the data on the list
157 __llist_node *nnode = new __llist_node;
159 nnode->setData(d);
160 nnode->setNext((__llist_node *) 0);
161 _last->setNext(nnode);
163 _last = nnode;
164 } else if (index < elements) {
165 // otherwise... insert the item at the position specified by index
166 __llist_node *nnode = new __llist_node, *inode = _first;
168 if (! nnode)
169 return -1;
171 nnode->setData(d);
173 for (register int i = 1; i < index; i++)
174 if (inode)
175 inode = inode->getNext();
176 else {
177 delete nnode;
178 return -1;
181 if ((! inode) || inode == _last) {
182 nnode->setNext((__llist_node *) 0);
183 _last->setNext(nnode);
185 _last = nnode;
186 } else {
187 nnode->setNext(inode->getNext());
188 inode->setNext(nnode);
193 return ++elements;
197 const int __llist::remove(void *d) {
198 // remove list item whose data pointer address matches the pointer address
199 // given
201 if ((! _first) || (! _last))
202 return -1;
203 else if (_first->getData() == d) {
204 // remove the first item in the list...
205 __llist_node *node = _first;
206 _first = _first->getNext();
208 if (iterators && iterators->_first) {
209 __llist_node *n = iterators->_first;
210 while (n) {
211 ((__llist_iterator *) n->getData())->reset();
212 n = n->getNext();
216 --elements;
217 delete node;
218 return 0;
219 } else {
220 // iterate through the list and remove the first occurance of the item
222 // NOTE: we don't validate _first in this assignment, because it is checked
223 // for validity above...
224 __llist_node *rnode = _first->getNext(), *prev = _first;
226 for (register int i = 1; i < elements; i++)
227 if (rnode)
228 if (rnode->getData() == d) {
229 // we found the item... update the previous node and delete the
230 // now useless rnode...
231 prev->setNext(rnode->getNext());
233 if (rnode == _last)
234 _last = prev;
236 if (iterators && iterators->_first) {
237 __llist_node *n = iterators->_first;
238 while (n) {
239 ((__llist_iterator *) n->getData())->reset();
240 n = n->getNext();
244 --elements;
245 delete rnode;
246 return i;
247 } else {
248 prev = rnode;
249 rnode = rnode->getNext();
252 return -1;
257 void *__llist::remove(const int index) {
258 if (index >= elements || index < 0 || (! _first) || (! _last))
259 return (void *) 0;
261 // remove list item at specified index within the list
262 if (index == 0) {
263 // remove the first item in the list...
264 __llist_node *node = _first;
265 void *data_return = _first->getData();
267 _first = _first->getNext();
269 if (iterators && iterators->_first) {
270 __llist_node *n = iterators->_first;
271 while (n) {
272 ((__llist_iterator *) n->getData())->reset();
273 n = n->getNext();
277 --elements;
278 delete node;
280 return data_return;
281 } else {
282 __llist_node *rnode = _first->getNext(), *prev = _first;
283 void *data_return = (void *) 0;
285 for (register int i = 1; i < index; i++)
286 if (rnode) {
287 prev = rnode;
288 rnode = rnode->getNext();
289 } else
290 return (void *) 0;
292 if (! rnode) return (void *) 0;
294 prev->setNext(rnode->getNext());
295 data_return = rnode->getData();
297 if (rnode == _last)
298 _last = prev;
300 if (iterators && iterators->_first) {
301 __llist_node *n = iterators->_first;
302 while (n) {
303 ((__llist_iterator *) n->getData())->reset();
304 n = n->getNext();
308 --elements;
309 data_return = rnode->getData();
310 delete rnode;
311 return data_return;
314 return (void *) 0;
318 void *__llist::find(const int index) {
319 if (index >= elements || index < 0 || (! _first) || (! _last))
320 return (void *) 0;
322 if (index == 0) {
323 // return the first item
324 return first();
325 } else if (index == (elements - 1)) {
326 // return the last item
327 return last();
328 } else {
329 __llist_node *fnode = _first->getNext();
331 for (register int i = 1; i < index; i++)
332 if (fnode)
333 fnode = fnode->getNext();
334 else
335 return (void *) 0;
337 return fnode->getData();
340 return (void *) 0;
344 void *__llist::first(void) {
345 if (_first)
346 return _first->getData();
348 return (void *) 0;
352 void *__llist::last(void) {
353 if (_last)
354 return _last->getData();
356 return (void *) 0;