2009-10-09 Chris Toshok <toshok@ximian.com>
[moon.git] / src / list.cpp
blob3db20889b6083e9eb41d68820af9d974a37f1df3
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);
40 List::Node *
41 List::First ()
43 return head;
47 List::Node *
48 List::Last ()
50 return tail;
54 bool
55 List::IsEmpty ()
57 return !head;
61 int
62 List::Length ()
64 return length;
68 void
69 List::Clear (bool freeNodes)
71 if (freeNodes) {
72 List::Node *n, *nn;
74 n = head;
75 while (n) {
76 nn = n->next;
77 delete n;
78 n = nn;
82 length = 0;
83 head = NULL;
84 tail = NULL;
88 List::Node *
89 List::Append (List::Node *node)
91 node->prev = tail;
92 node->next = NULL;
94 if (tail)
95 tail->next = node;
96 else
97 head = node;
99 tail = node;
101 length++;
103 return node;
107 List::Node *
108 List::Prepend (List::Node *node)
110 node->next = head;
111 node->prev = NULL;
113 if (head)
114 head->prev = node;
115 else
116 tail = node;
118 head = node;
120 length++;
122 return node;
126 List::Node *
127 List::Insert (List::Node *node, int index)
129 List::Node *n = head;
130 int i = 0;
132 if (head) {
133 while (n->next && i < index) {
134 n = n->next;
135 i++;
138 if (i == index) {
139 // Inserting @node before @n
140 node->prev = n->prev;
141 node->next = n;
143 if (n->prev)
144 n->prev->next = node;
145 else
146 head = node;
148 n->prev = node;
149 } else {
150 // Inserting @node after @n (means @n was the tail)
151 tail = n->next = node;
152 node->prev = n;
153 node->next = NULL;
155 } else {
156 // @node will be the only node in the list
157 head = tail = node;
158 node->next = NULL;
159 node->prev = NULL;
162 length++;
164 return node;
167 List::Node *
168 List::InsertAfter (List::Node *node, List::Node *after)
170 if (after == NULL)
171 return Prepend (node);
173 node->next = after->next;
174 node->prev = after;
175 after->next = node;
177 if (node->next != NULL)
178 node->next->prev = node;
179 else
180 tail = node;
182 length++;
184 return node;
187 List::Node *
188 List::InsertBefore (List::Node *node, List::Node *before)
190 if (before == NULL)
191 return Append (node);
193 node->next = before;
194 node->prev = before->prev;
196 if (before->prev != NULL)
197 before->prev->next = node;
198 else
199 head = node;
201 before->prev = node;
203 length++;
205 return node;
209 List::Node *
210 List::Replace (List::Node *node, int index)
212 List::Node *n;
214 if (!(n = Index (index)))
215 return NULL;
217 node->next = n->next;
218 node->prev = n->prev;
220 if (n->prev)
221 n->prev->next = node;
222 else
223 head = node;
225 if (n->next)
226 n->next->prev = node;
227 else
228 tail = node;
230 n->next = NULL;
231 n->prev = NULL;
233 return n;
236 List::Node *
237 List::Find (NodeAction find, void *data)
239 List::Node *n = head;
241 if (!find)
242 return NULL;
244 while (n) {
245 if (find (n, data))
246 return n;
248 n = n->next;
251 return NULL;
255 void
256 List::Remove (NodeAction find, void *data)
258 List::Node *n;
260 if ((n = Find (find, data))) {
261 Unlink (n);
262 delete n;
266 void
267 List::Remove (List::Node *node)
269 Unlink (node);
270 delete node;
273 void
274 List::RemoveAt (int index)
276 List::Node *node;
277 if (!(node = Index (index)))
278 return;
280 Unlink (node);
281 delete node;
284 void
285 List::Unlink (List::Node *node)
287 if (node->prev)
288 node->prev->next = node->next;
289 else
290 head = node->next;
292 if (node->next)
293 node->next->prev = node->prev;
294 else
295 tail = node->prev;
297 node->prev = NULL;
298 node->next = NULL;
300 length--;
304 List::Node *
305 List::Index (int index)
307 List::Node *n = head;
308 int i = 0;
310 if (index < 0)
311 return NULL;
313 while (n && i < index) {
314 n = n->next;
315 i++;
318 if (i == index)
319 return n;
321 return NULL;
325 List::IndexOf (List::Node *node)
327 List::Node *n = head;
328 int i = 0;
330 while (n && n != node) {
331 n = n->next;
332 i++;
335 return n == node ? i : -1;
340 List::IndexOf (NodeAction find, void *data)
342 List::Node *n = head;
343 int i = 0;
345 if (!find)
346 return -1;
348 while (n) {
349 if (find (n, data))
350 return i;
352 n = n->next;
353 i++;
356 return -1;
359 void
360 List::ForEach (NodeAction action, void *data)
362 List::Node *node = head;
363 bool move = true;
365 if (!action)
366 return;
368 while (node && move) {
369 if (!action (node, data))
370 move = false;
371 else
372 node = node->next;
377 Queue::Queue ()
379 pthread_mutex_init (&lock, NULL);
380 list = new List ();
383 Queue::~Queue ()
385 pthread_mutex_destroy (&lock);
386 delete list;
389 bool
390 Queue::IsEmpty ()
392 bool empty;
394 Lock ();
395 empty = list->IsEmpty ();
396 Unlock ();
398 return empty;
402 Queue::Length ()
404 int length;
406 Lock ();
407 length = list->Length ();
408 Unlock ();
410 return length;
413 void
414 Queue::Clear (bool freeNodes)
416 Lock ();
417 list->Clear (freeNodes);
418 Unlock ();
421 void
422 Queue::Push (List::Node *node)
424 Lock ();
425 list->Append (node);
426 Unlock ();
429 List::Node *
430 Queue::Pop ()
432 List::Node *node;
434 Lock ();
435 if ((node = list->First ()))
436 list->Unlink (node);
437 Unlock ();
439 return node;
442 void
443 Queue::Lock ()
445 pthread_mutex_lock (&lock);
448 void
449 Queue::Unlock ()
451 pthread_mutex_unlock (&lock);
454 List *
455 Queue::LinkedList ()
457 return list;
462 * ArrayList
465 ArrayList::ArrayList ()
467 array = NULL;
468 size = 0;
469 count = 0;
472 ArrayList::~ArrayList ()
474 g_free (array);
478 ArrayList::GetCount ()
480 return count;
483 void
484 ArrayList::SetCount (int value)
486 EnsureCapacity (value);
487 count = value;
491 ArrayList::GetCapacity ()
493 return size;
496 void
497 ArrayList::SetCapacity (int capacity)
499 if (capacity == size)
500 return;
502 array = (void **) g_realloc (array, sizeof (void *) * capacity);
504 for (int i = size; i < capacity; i++)
505 array [i] = NULL;
506 size = capacity;
509 void
510 ArrayList::EnsureCapacity (int capacity)
512 if (size < capacity)
513 SetCapacity (capacity);
517 ArrayList::Add (void *item)
519 EnsureCapacity (count + 1);
520 array [count] = item;
521 return count++;
524 void *&
525 ArrayList::operator [] (int index)
527 return array [index];
531 //#define TEST_PROGRAM
532 #ifdef TEST_PROGRAM
534 #include <stdio.h>
536 class IntNode : public List::Node {
537 public:
538 int id;
540 IntNode (int i) { id = i; }
544 static int
545 IntNodeCompare (List::Node *n0, List::Node *n1)
547 IntNode *in0 = (IntNode *) n0;
548 IntNode *in1 = (IntNode *) n1;
550 return in0->id - in1->id;
553 static bool
554 IntNodeFinder (List::Node *node, void *data)
556 int val = *((int *) data);
558 return ((IntNode *) node)->id == val;
562 int main (int argc, char **argv)
564 List::Node *node;
565 List *list;
567 list = new List ();
569 node = list->Append (new IntNode (2));
570 printf ("appended node with id = %d\n", ((IntNode *) node)->id);
571 node = list->Append (new IntNode (4));
572 printf ("appended node with id = %d\n", ((IntNode *) node)->id);
573 node = list->Append (new IntNode (5));
574 printf ("appended node with id = %d\n", ((IntNode *) node)->id);
575 node = list->Insert (new IntNode (3), 1);
576 printf ("inserted node with id = %d at index = %d\n",
577 ((IntNode *) node)->id, list->IndexOf (node));
578 node = list->Prepend (new IntNode (1));
579 printf ("prepended node with id = %d\n", ((IntNode *) node)->id);
580 node = list->Prepend (new IntNode (0));
581 printf ("prepended node with id = %d\n", ((IntNode *) node)->id);
582 node = list->Insert (new IntNode (6), 6);
583 printf ("inserted node with id = %d at index = %d\n",
584 ((IntNode *) node)->id, list->IndexOf (node));
586 printf ("\nlist contains (in order):\n");
587 for (node = list->First (); node != NULL; node = node->next)
588 printf ("node id = %d\n", ((IntNode *) node)->id);
590 printf ("\nlist contains (in reverse order):\n");
591 for (node = list->Last (); node != NULL; node = node->prev)
592 printf ("node id = %d\n", ((IntNode *) node)->id);
594 printf ("\nunlinking the last item in the list\n");
595 list->Unlink (list->Last ());
597 printf ("\nlist contains (in order):\n");
598 for (node = list->First (); node != NULL; node = node->next)
599 printf ("node id = %d\n", ((IntNode *) node)->id);
601 printf ("\nlist contains (in reverse order):\n");
602 for (node = list->Last (); node != NULL; node = node->prev)
603 printf ("node id = %d\n", ((IntNode *) node)->id);
605 printf ("\nunlinking the first item in the list\n");
606 list->Unlink (list->First ());
608 printf ("\nlist contains (in order):\n");
609 for (node = list->First (); node != NULL; node = node->next)
610 printf ("node id = %d\n", ((IntNode *) node)->id);
612 printf ("\nlist contains (in reverse order):\n");
613 for (node = list->Last (); node != NULL; node = node->prev)
614 printf ("node id = %d\n", ((IntNode *) node)->id);
616 printf ("\nreplacing 4 with 8\n");
617 int id = 4;
618 int index = list->IndexOf (IntNodeFinder, &id);
619 if ((node = list->Replace (new IntNode (8), index)))
620 delete node;
621 else
622 printf ("unsuccessful\n");
624 printf ("\nlist contains (in order):\n");
625 for (node = list->First (); node != NULL; node = node->next)
626 printf ("node id = %d\n", ((IntNode *) node)->id);
628 printf ("\nlist contains (in reverse order):\n");
629 for (node = list->Last (); node != NULL; node = node->prev)
630 printf ("node id = %d\n", ((IntNode *) node)->id);
632 printf ("\nremoving 5\n");
633 id = 5;
634 list->Remove (IntNodeFinder, &id);
636 printf ("\nlist contains (in order):\n");
637 for (node = list->First (); node != NULL; node = node->next)
638 printf ("node id = %d\n", ((IntNode *) node)->id);
640 printf ("\nlist contains (in reverse order):\n");
641 for (node = list->Last (); node != NULL; node = node->prev)
642 printf ("node id = %d\n", ((IntNode *) node)->id);
644 printf ("\nremoving 1\n");
645 id = 1;
646 list->Remove (IntNodeFinder, &id);
648 printf ("\nlist contains (in order):\n");
649 for (node = list->First (); node != NULL; node = node->next)
650 printf ("node id = %d\n", ((IntNode *) node)->id);
652 printf ("\nlist contains (in reverse order):\n");
653 for (node = list->Last (); node != NULL; node = node->prev)
654 printf ("node id = %d\n", ((IntNode *) node)->id);
656 list->Clear (true);
657 delete list;
659 return 0;
662 #endif /* TEST_PROGRAM */