2009-12-03 Jeffrey Stedfast <fejj@novell.com>
[moon.git] / src / list.cpp
blobf6c96f32050a5153dc044a4e0db9eaffa97c70a8
1 /*
2 * list.cpp: a non-sucky linked list implementation
4 * Contact:
5 * Moonlight List (moonlight-list@lists.ximian.com)
7 * Copyright 2007 Novell, Inc. (http://www.novell.com)
9 * See the LICENSE file included with the distribution for details.
13 #include <config.h>
15 #include <glib.h>
16 #include "list.h"
19 List::Node::Node ()
21 next = NULL;
22 prev = NULL;
26 List::List ()
28 length = 0;
29 head = NULL;
30 tail = NULL;
34 List::~List ()
36 Clear (true);
39 List::Node *
40 List::Last ()
42 return tail;
46 bool
47 List::IsEmpty ()
49 return !head;
53 int
54 List::Length ()
56 return length;
60 void
61 List::Clear (bool freeNodes)
63 if (freeNodes) {
64 List::Node *n, *nn;
66 n = head;
67 while (n) {
68 nn = n->next;
69 delete n;
70 n = nn;
74 length = 0;
75 head = NULL;
76 tail = NULL;
80 List::Node *
81 List::Append (List::Node *node)
83 node->prev = tail;
84 node->next = NULL;
86 if (tail)
87 tail->next = node;
88 else
89 head = node;
91 tail = node;
93 length++;
95 return node;
99 List::Node *
100 List::Prepend (List::Node *node)
102 node->next = head;
103 node->prev = NULL;
105 if (head)
106 head->prev = node;
107 else
108 tail = node;
110 head = node;
112 length++;
114 return node;
117 List::Node *
118 List::Prepend (List *list)
120 if (list->head == NULL)
121 return head;
123 list->tail->next = head;
124 if (head)
125 head->prev = list->tail;
126 else
127 tail = list->tail;
129 head = list->head;
131 length += list->length;
133 return head;
137 List::Node *
138 List::Insert (List::Node *node, int index)
140 List::Node *n = head;
141 int i = 0;
143 if (head) {
144 while (n->next && i < index) {
145 n = n->next;
146 i++;
149 if (i == index) {
150 // Inserting @node before @n
151 node->prev = n->prev;
152 node->next = n;
154 if (n->prev)
155 n->prev->next = node;
156 else
157 head = node;
159 n->prev = node;
160 } else {
161 // Inserting @node after @n (means @n was the tail)
162 tail = n->next = node;
163 node->prev = n;
164 node->next = NULL;
166 } else {
167 // @node will be the only node in the list
168 head = tail = node;
169 node->next = NULL;
170 node->prev = NULL;
173 length++;
175 return node;
178 List::Node *
179 List::InsertAfter (List::Node *node, List::Node *after)
181 if (after == NULL)
182 return Prepend (node);
184 node->next = after->next;
185 node->prev = after;
186 after->next = node;
188 if (node->next != NULL)
189 node->next->prev = node;
190 else
191 tail = node;
193 length++;
195 return node;
198 List::Node *
199 List::InsertBefore (List::Node *node, List::Node *before)
201 if (before == NULL)
202 return Append (node);
204 node->next = before;
205 node->prev = before->prev;
207 if (before->prev != NULL)
208 before->prev->next = node;
209 else
210 head = node;
212 before->prev = node;
214 length++;
216 return node;
220 List::Node *
221 List::Replace (List::Node *node, int index)
223 List::Node *n;
225 if (!(n = Index (index)))
226 return NULL;
228 node->next = n->next;
229 node->prev = n->prev;
231 if (n->prev)
232 n->prev->next = node;
233 else
234 head = node;
236 if (n->next)
237 n->next->prev = node;
238 else
239 tail = node;
241 n->next = NULL;
242 n->prev = NULL;
244 return n;
247 List::Node *
248 List::Find (NodeAction find, void *data)
250 List::Node *n = head;
252 if (!find)
253 return NULL;
255 while (n) {
256 if (find (n, data))
257 return n;
259 n = n->next;
262 return NULL;
266 void
267 List::Remove (NodeAction find, void *data)
269 List::Node *n;
271 if ((n = Find (find, data))) {
272 Unlink (n);
273 delete n;
277 void
278 List::Remove (List::Node *node)
280 Unlink (node);
281 delete node;
284 void
285 List::RemoveAt (int index)
287 List::Node *node;
288 if (!(node = Index (index)))
289 return;
291 Unlink (node);
292 delete node;
295 void
296 List::Unlink (List::Node *node)
298 if (node->prev)
299 node->prev->next = node->next;
300 else
301 head = node->next;
303 if (node->next)
304 node->next->prev = node->prev;
305 else
306 tail = node->prev;
308 node->prev = NULL;
309 node->next = NULL;
311 length--;
315 List::Node *
316 List::Index (int index)
318 List::Node *n = head;
319 int i = 0;
321 if (index < 0)
322 return NULL;
324 while (n && i < index) {
325 n = n->next;
326 i++;
329 if (i == index)
330 return n;
332 return NULL;
336 List::IndexOf (List::Node *node)
338 List::Node *n = head;
339 int i = 0;
341 while (n && n != node) {
342 n = n->next;
343 i++;
346 return n == node ? i : -1;
351 List::IndexOf (NodeAction find, void *data)
353 List::Node *n = head;
354 int i = 0;
356 if (!find)
357 return -1;
359 while (n) {
360 if (find (n, data))
361 return i;
363 n = n->next;
364 i++;
367 return -1;
370 void
371 List::ForEach (NodeAction action, void *data)
373 List::Node *node = head;
374 bool move = true;
376 if (!action)
377 return;
379 while (node && move) {
380 if (!action (node, data))
381 move = false;
382 else
383 node = node->next;
388 Queue::Queue ()
390 pthread_mutex_init (&lock, NULL);
391 list = new List ();
394 Queue::~Queue ()
396 pthread_mutex_destroy (&lock);
397 delete list;
400 bool
401 Queue::IsEmpty ()
403 bool empty;
405 Lock ();
406 empty = list->IsEmpty ();
407 Unlock ();
409 return empty;
413 Queue::Length ()
415 int length;
417 Lock ();
418 length = list->Length ();
419 Unlock ();
421 return length;
424 void
425 Queue::Clear (bool freeNodes)
427 Lock ();
428 list->Clear (freeNodes);
429 Unlock ();
432 void
433 Queue::Push (List::Node *node)
435 Lock ();
436 list->Append (node);
437 Unlock ();
440 List::Node *
441 Queue::Pop ()
443 List::Node *node;
445 Lock ();
446 if ((node = list->First ()))
447 list->Unlink (node);
448 Unlock ();
450 return node;
453 void
454 Queue::Lock ()
456 pthread_mutex_lock (&lock);
459 void
460 Queue::Unlock ()
462 pthread_mutex_unlock (&lock);
465 List *
466 Queue::LinkedList ()
468 return list;
471 void
472 Queue::MoveTo (Queue &queue)
474 List::Node *node;
475 while ((node = list->First ())) {
476 list->Unlink (node);
477 queue.Push (node);
483 * ArrayList
486 ArrayList::ArrayList ()
488 array = NULL;
489 size = 0;
490 count = 0;
493 ArrayList::~ArrayList ()
495 g_free (array);
498 void
499 ArrayList::SetCount (int value)
501 EnsureCapacity (value);
502 count = value;
506 ArrayList::GetCapacity ()
508 return size;
511 void
512 ArrayList::SetCapacity (int capacity)
514 if (capacity == size)
515 return;
517 array = (void **) g_realloc (array, sizeof (void *) * capacity);
519 for (int i = size; i < capacity; i++)
520 array [i] = NULL;
521 size = capacity;
524 void
525 ArrayList::EnsureCapacity (int capacity)
527 if (size < capacity)
528 SetCapacity (capacity);
532 ArrayList::Add (void *item)
534 EnsureCapacity (count + 1);
535 array [count] = item;
536 return count++;
539 //#define TEST_PROGRAM
540 #ifdef TEST_PROGRAM
542 #include <stdio.h>
544 class IntNode : public List::Node {
545 public:
546 int id;
548 IntNode (int i) { id = i; }
552 static bool
553 IntNodeFinder (List::Node *node, void *data)
555 int val = *((int *) data);
557 return ((IntNode *) node)->id == val;
561 int main (int argc, char **argv)
563 List::Node *node;
564 List *list;
566 list = new List ();
568 node = list->Append (new IntNode (2));
569 printf ("appended node with id = %d\n", ((IntNode *) node)->id);
570 node = list->Append (new IntNode (4));
571 printf ("appended node with id = %d\n", ((IntNode *) node)->id);
572 node = list->Append (new IntNode (5));
573 printf ("appended node with id = %d\n", ((IntNode *) node)->id);
574 node = list->Insert (new IntNode (3), 1);
575 printf ("inserted node with id = %d at index = %d\n",
576 ((IntNode *) node)->id, list->IndexOf (node));
577 node = list->Prepend (new IntNode (1));
578 printf ("prepended node with id = %d\n", ((IntNode *) node)->id);
579 node = list->Prepend (new IntNode (0));
580 printf ("prepended node with id = %d\n", ((IntNode *) node)->id);
581 node = list->Insert (new IntNode (6), 6);
582 printf ("inserted node with id = %d at index = %d\n",
583 ((IntNode *) node)->id, list->IndexOf (node));
585 printf ("\nlist contains (in order):\n");
586 for (node = list->First (); node != NULL; node = node->next)
587 printf ("node id = %d\n", ((IntNode *) node)->id);
589 printf ("\nlist contains (in reverse order):\n");
590 for (node = list->Last (); node != NULL; node = node->prev)
591 printf ("node id = %d\n", ((IntNode *) node)->id);
593 printf ("\nunlinking the last item in the list\n");
594 list->Unlink (list->Last ());
596 printf ("\nlist contains (in order):\n");
597 for (node = list->First (); node != NULL; node = node->next)
598 printf ("node id = %d\n", ((IntNode *) node)->id);
600 printf ("\nlist contains (in reverse order):\n");
601 for (node = list->Last (); node != NULL; node = node->prev)
602 printf ("node id = %d\n", ((IntNode *) node)->id);
604 printf ("\nunlinking the first item in the list\n");
605 list->Unlink (list->First ());
607 printf ("\nlist contains (in order):\n");
608 for (node = list->First (); node != NULL; node = node->next)
609 printf ("node id = %d\n", ((IntNode *) node)->id);
611 printf ("\nlist contains (in reverse order):\n");
612 for (node = list->Last (); node != NULL; node = node->prev)
613 printf ("node id = %d\n", ((IntNode *) node)->id);
615 printf ("\nreplacing 4 with 8\n");
616 int id = 4;
617 int index = list->IndexOf (IntNodeFinder, &id);
618 if ((node = list->Replace (new IntNode (8), index)))
619 delete node;
620 else
621 printf ("unsuccessful\n");
623 printf ("\nlist contains (in order):\n");
624 for (node = list->First (); node != NULL; node = node->next)
625 printf ("node id = %d\n", ((IntNode *) node)->id);
627 printf ("\nlist contains (in reverse order):\n");
628 for (node = list->Last (); node != NULL; node = node->prev)
629 printf ("node id = %d\n", ((IntNode *) node)->id);
631 printf ("\nremoving 5\n");
632 id = 5;
633 list->Remove (IntNodeFinder, &id);
635 printf ("\nlist contains (in order):\n");
636 for (node = list->First (); node != NULL; node = node->next)
637 printf ("node id = %d\n", ((IntNode *) node)->id);
639 printf ("\nlist contains (in reverse order):\n");
640 for (node = list->Last (); node != NULL; node = node->prev)
641 printf ("node id = %d\n", ((IntNode *) node)->id);
643 printf ("\nremoving 1\n");
644 id = 1;
645 list->Remove (IntNodeFinder, &id);
647 printf ("\nlist contains (in order):\n");
648 for (node = list->First (); node != NULL; node = node->next)
649 printf ("node id = %d\n", ((IntNode *) node)->id);
651 printf ("\nlist contains (in reverse order):\n");
652 for (node = list->Last (); node != NULL; node = node->prev)
653 printf ("node id = %d\n", ((IntNode *) node)->id);
655 list->Clear (true);
656 delete list;
658 return 0;
661 #endif /* TEST_PROGRAM */