Add _DEBUG/NDEBUG defines when DEBUG/NODEBUG options are used, respectively
[openal-soft.git] / Router / alList.cpp
blob2c884c5671bb4f20f01b37df236982166e2fa567
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2003 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
24 #include "alList.h"
25 #include <windows.h>
26 #include <stdio.h>
27 #include <stdlib.h>
30 //****************************************************************************
31 //****************************************************************************
33 // Defines
35 //****************************************************************************
36 //****************************************************************************
39 // Some occasionally useful debugging stuff.
41 #if(DBG)
42 #ifndef ASSERT
43 static ALint alListDebugAssertsEnabled = 1;
44 #define ASSERT(exp) \
45 { \
46 if(!(exp) && alListDebugAssertsEnabled) \
47 { \
48 char tempStr[256]; \
49 OutputDebugString("\n"); \
50 sprintf(tempStr, "Assert failed in file %s, line %d!\n", \
51 __FILE__, __LINE__); \
52 OutputDebugString(tempStr); \
53 OutputDebugString("\n"); \
54 if(alListDebugAssertsEnabled) \
55 { \
56 DebugBreak(); \
57 } \
58 } \
61 #endif
62 #else
63 #ifndef ASSERT
64 #define ASSERT(exp)
65 #endif
66 #endif
70 //****************************************************************************
71 //****************************************************************************
73 // List Functions
75 //****************************************************************************
76 //****************************************************************************
78 //*****************************************************************************
79 // alListAddEntry
80 //*****************************************************************************
81 // Adds an entry to the tail of the list. Each entry must be unique.
83 ALvoid alListAddEntry
85 IN ALlist* pList,
86 IN ALlistEntry* pEntry
89 #if(DBG)
90 ALlistEntry* pCurrent = 0;
91 #endif
93 ASSERT(pList);
94 ASSERT(pEntry);
95 ASSERT(pList->Locked);
96 ASSERT(!pEntry->Next);
97 ASSERT(!pEntry->Previous);
100 // Verify the entry doesn't already exist.
102 #if(DBG)
103 pCurrent = pList->Head;
104 while(pCurrent)
106 if(pCurrent == pEntry)
108 break;
111 pCurrent = pCurrent->Next;
114 if(pCurrent)
116 // Duplicate entries are not supported.
117 ASSERT(0);
118 return;
120 #endif
124 // Add the item to the tail of the list.
126 if(pList->Tail)
128 pList->Tail->Next = pEntry;
131 pEntry->Previous = pList->Tail;
132 pList->Tail = pEntry;
135 // Check if this is the first entry.
137 if(!pList->Head)
139 pList->Head = pEntry;
140 pList->Current = pEntry;
143 pList->NumberOfEntries++;
147 //*****************************************************************************
148 // alListAddEntryToHead
149 //*****************************************************************************
150 // Adds an entry to the head of the list. Each entry must be unique.
152 ALvoid alListAddEntryToHead
154 IN ALlist* pList,
155 IN ALlistEntry* pEntry
158 #if(DBG)
159 ALlistEntry* pCurrent = 0;
160 #endif
161 ASSERT(pList);
162 ASSERT(pEntry);
163 ASSERT(pList->Locked);
164 ASSERT(!pEntry->Next);
165 ASSERT(!pEntry->Previous);
168 // Verify the entry doesn't already exist.
170 #if(DBG)
171 pCurrent = pList->Head;
172 while(pCurrent)
174 if(pCurrent == pEntry)
176 break;
179 pCurrent = pCurrent->Next;
182 if(pCurrent)
184 // Duplicate entries are not supported.
185 ASSERT(0);
186 return;
188 #endif
192 // Add the item to the head of the list.
194 if(pList->Head)
196 pList->Head->Previous = pEntry;
199 pEntry->Next = pList->Head;
200 pList->Head = pEntry;
203 // Check if this is the first entry.
205 if(!pList->Tail)
207 pList->Tail = pEntry;
208 pList->Current = pEntry;
211 pList->NumberOfEntries++;
215 //*****************************************************************************
216 // alListAcquireLock
217 //*****************************************************************************
218 // This is called to aquire the list lock for operations that span multiple
219 // list calls like iterating over the list.
221 ALvoid alListAcquireLock
223 IN ALlist* pList
226 ASSERT(pList);
228 EnterCriticalSection(&pList->Lock);
229 #if(DBG)
230 pList->Locked++;
231 #endif
234 // Check that only one person has the lock.
236 ASSERT(pList->Locked == 1);
240 //*****************************************************************************
241 // alListCreate
242 //*****************************************************************************
243 // Creates and initializes a list.
245 ALboolean alListCreate
247 OUT ALlist** ppList
250 ALlist* pList = 0;
252 ASSERT(ppList);
255 // Allocate and initialize the list context.
257 *ppList = 0;
258 pList = (ALlist*)malloc(sizeof(ALlist));
259 if(!pList)
261 // Failed to allocate the list!
262 ASSERT(0);
263 return FALSE;
266 memset(pList, 0, sizeof(ALlist));
267 InitializeCriticalSection(&pList->Lock);
268 pList->NumberOfEntries = 0;
269 *ppList = pList;
270 return TRUE;
274 //*****************************************************************************
275 // alListFree
276 //*****************************************************************************
277 // Destroys the list.
279 ALvoid alListFree
281 IN ALlist* pList
284 ASSERT(pList);
285 ASSERT(!pList->Head);
288 // Free the resources allocated during the creation.
290 if(pList)
292 DeleteCriticalSection(&pList->Lock);
293 free(pList);
296 return;
300 //*****************************************************************************
301 // alListGetData
302 //*****************************************************************************
303 // Returns the data from the list entry.
305 ALvoid* alListGetData
307 IN ALlistEntry* pEntry
310 ASSERT(pEntry);
312 return pEntry->Data;
316 //*****************************************************************************
317 // alListGetEntryAt
318 //*****************************************************************************
319 // Returns the entry in the list at the specified index of the list.
321 ALlistEntry* alListGetEntryAt
323 IN ALlist* pList,
324 IN ALint Index
327 ALlistEntry* pEntry = 0;
328 ALint i;
330 ASSERT(pList);
331 ASSERT(pList->Locked);
332 ASSERT(Index < pList->NumberOfEntries);
334 pEntry = pList->Head;
335 for(i = 0; i < Index && pEntry; i++)
337 pEntry = pEntry->Next;
340 return pEntry;
344 //*****************************************************************************
345 // alListGetEntryCount
346 //*****************************************************************************
347 // Returns the number of items stored in the list.
349 ALint alListGetEntryCount
351 IN ALlist* pList
354 ASSERT(pList->Locked);
355 return pList->NumberOfEntries;
359 //*****************************************************************************
360 // alListGetHead
361 //*****************************************************************************
362 // Returns the first entry in the list.
364 ALlistEntry* alListGetHead
366 IN ALlist* pList
369 ASSERT(pList);
370 ASSERT(pList->Locked);
372 return pList->Head;
376 //*****************************************************************************
377 // alListGetNext
378 //*****************************************************************************
379 // Returns the entry after to the entry pointed to by the iterator. If
380 // the iterator is at the last entry (or has finished iterating over the
381 // list), the returned entry will be 0.
383 ALlistEntry* alListGetNext
385 IN ALlist* pList
388 ASSERT(pList);
389 ASSERT(pList->Locked);
391 if(!pList->Current)
393 return 0;
396 return pList->Current->Next;
400 //*****************************************************************************
401 // alListGetPrevious
402 //*****************************************************************************
403 // Returns the entry previous to the entry pointed to by the iterator. If
404 // the iterator is at the first entry, the returned entry will be 0.
406 ALlistEntry* alListGetPrevious
408 IN ALlist* pList
411 ASSERT(pList);
412 ASSERT(pList->Locked);
414 if(!pList->Current)
416 return 0;
419 return pList->Current->Previous;
423 //*****************************************************************************
424 // alListGetTail
425 //*****************************************************************************
426 // Returns the last entry in the list.
428 ALlistEntry* alListGetTail
430 IN ALlist* pList
433 ASSERT(pList);
434 ASSERT(pList->Locked);
436 return pList->Tail;
440 //*****************************************************************************
441 // alListInitializeEntry
442 //*****************************************************************************
443 // Initializes a preallocated list entry.
445 ALvoid alListInitializeEntry
447 ALlistEntry* pEntry,
448 ALvoid* pData
451 ASSERT(pEntry);
453 pEntry->Data = pData;
454 pEntry->Next = 0;
455 pEntry->Previous = 0;
459 //*****************************************************************************
460 // alListIsEmpty
461 //*****************************************************************************
462 // Returns the TRUE if the list is empty.
464 ALboolean alListIsEmpty
466 IN ALlist* pList
469 ASSERT(pList);
470 ASSERT(pList->Locked);
472 return (pList->Head == 0);
476 //*****************************************************************************
477 // alListIteratorGet
478 //*****************************************************************************
479 // Returns the entry pointed to by the iterator.
481 ALlistEntry* alListIteratorGet
483 IN ALlist* pList
486 ASSERT(pList);
487 ASSERT(pList->Locked);
489 return pList->Current;
493 //*****************************************************************************
494 // alListIteratorFindData
495 //*****************************************************************************
496 // Searches the list for the matching item and return the pointer to the
497 // entry. If the match is not found, the return will be 0.
499 ALlistEntry* alListIteratorFindData
501 IN ALlist* pList,
502 IN ALvoid* pData
505 ALlistEntry* pCurrent = 0;
507 ASSERT(pList);
508 ASSERT(pList->Locked);
511 // Find the item.
513 pCurrent = pList->Head;
514 while(pCurrent)
516 if(pCurrent->Data == pData)
518 break;
521 pCurrent = pCurrent->Next;
524 pList->Current = pCurrent;
525 return pCurrent;
529 //*****************************************************************************
530 // alListIteratorNext
531 //*****************************************************************************
532 // This is called to advance the list iterator to the next entry in the list
533 // and return that entry.
535 ALlistEntry* alListIteratorNext
537 IN ALlist* pList
540 ASSERT(pList);
541 ASSERT(pList->Locked);
543 if(!pList->Current)
545 return 0;
548 pList->Current = pList->Current->Next;
549 return pList->Current;
553 //*****************************************************************************
554 // alListIteratorPrevious
555 //*****************************************************************************
556 // This is called to advance the list iterator to the previous entry in the
557 // list and return that entry.
559 ALlistEntry* alListIteratorPrevious
561 IN ALlist* pList
564 ASSERT(pList);
565 ASSERT(pList->Locked);
567 if(!pList->Current)
569 return 0;
572 pList->Current = pList->Current->Previous;
573 return pList->Current;
577 //*****************************************************************************
578 // alListIteratorRemove
579 //*****************************************************************************
580 // Removes the current item from the list and returns it. The iterator will
581 // equal the next item in the list.
583 ALlistEntry* alListIteratorRemove
585 IN ALlist* pList
588 ALlistEntry* pEntry = 0;
590 ASSERT(pList);
591 ASSERT(pList->Locked);
594 // Make sure we aren't at the end of the list.
596 if(!pList->Current)
598 return 0;
602 // Remove the item from the list.
604 pEntry = pList->Current;
607 // Fix up the next item in the list.
609 if(pEntry->Next)
611 pEntry->Next->Previous = pEntry->Previous;
615 // Fix up the previous item in the list.
617 if(pEntry->Previous)
619 pEntry->Previous->Next = pEntry->Next;
623 // Fix up the current pointer.
625 pList->Current = pEntry->Next;
628 // Check the head pointer.
630 if(pList->Head == pEntry)
632 pList->Head = pEntry->Next;
636 // Check the tail pointer.
638 if(pList->Tail == pEntry)
640 pList->Tail = pEntry->Previous;
644 // Set the entry pointers.
646 pEntry->Next = 0;
647 pEntry->Previous = 0;
648 pList->NumberOfEntries--;
649 ASSERT(0 <= pList->NumberOfEntries);
650 return pEntry;
654 //*****************************************************************************
655 // alListIteratorReset
656 //*****************************************************************************
657 // Returns the list iterator to the head of the list.
659 ALlistEntry* alListIteratorReset
661 IN ALlist* pList
664 ASSERT(pList);
665 ASSERT(pList->Locked);
667 pList->Current = pList->Head;
668 return pList->Current;
672 //*****************************************************************************
673 // alListIteratorSet
674 //*****************************************************************************
675 // Sets the current entry pointer to the entry passed in. If the entry is not
676 // found, the current entry will be 0.
678 ALlistEntry* alListIteratorSet
680 IN ALlist* pList,
681 IN ALlistEntry* pEntry
684 ALlistEntry* pCurrent = 0;
686 ASSERT(pList);
687 ASSERT(pList->Locked);
689 pCurrent = pList->Head;
690 while(pCurrent)
692 if(pCurrent == pEntry)
694 break;
697 pCurrent = pCurrent->Next;
700 pList->Current = pCurrent;
701 return pList->Current;
705 //*****************************************************************************
706 // alListMatchEntry
707 //*****************************************************************************
708 // Matches the entry to an item in the list and returns the data in that
709 // entry. If the match is not found, the return will be 0.
711 ALvoid* alListMatchEntry
713 IN ALlist* pList,
714 IN ALlistEntry* pEntry
717 ALlistEntry* pCurrent = 0;
719 ASSERT(pList);
720 ASSERT(pList->Locked);
723 // Find the item.
725 pCurrent = pList->Head;
726 while(pCurrent)
728 if(pCurrent == pEntry)
730 break;
733 pCurrent = pCurrent->Next;
736 if(!pCurrent)
738 return 0;
741 return pCurrent->Data;
745 //*****************************************************************************
746 // alListMatchData
747 //*****************************************************************************
748 // Searches the list for the first matching item and returns the pointer to
749 // the entry. If the match is not found, the return will be 0.
751 ALlistEntry* alListMatchData
753 IN ALlist* pList,
754 IN ALvoid* pData
757 ALlistEntry* pCurrent = 0;
759 ASSERT(pList);
760 ASSERT(pList->Locked);
763 // Find the item.
765 pCurrent = pList->Head;
766 while(pCurrent)
768 if(pCurrent->Data == pData)
770 break;
773 pCurrent = pCurrent->Next;
776 return pCurrent;
780 //*****************************************************************************
781 // alListReleaseLock
782 //*****************************************************************************
783 // This is called to release the list lock.
785 ALvoid alListReleaseLock
787 IN ALlist* pList
790 ASSERT(pList);
791 ASSERT(pList->Locked);
793 #if(DBG)
794 pList->Locked--;
795 ASSERT(pList->Locked == 0);
796 #endif
798 LeaveCriticalSection(&pList->Lock);
802 //*****************************************************************************
803 // alListRemoveEntry
804 //*****************************************************************************
805 // Removes the item from the list and returns the data from the item. If
806 // this is the current item, the current item will equal the next item in the
807 // list.
809 ALvoid* alListRemoveEntry
811 IN ALlist* pList,
812 IN ALlistEntry* pEntry
815 ALlistEntry* pCurrent = 0;
817 ASSERT(pList);
818 ASSERT(pList->Locked);
819 ASSERT(pEntry);
822 // Release the item from the list.
824 pCurrent = pList->Head;
825 while(pCurrent)
827 if(pCurrent == pEntry)
829 break;
832 pCurrent = pCurrent->Next;
835 if(!pCurrent)
837 return 0;
841 // Fix up the next item in the list.
843 if(pEntry->Next)
845 pEntry->Next->Previous = pEntry->Previous;
849 // Fix up the previous item in the list.
851 if(pEntry->Previous)
853 pEntry->Previous->Next = pEntry->Next;
857 // Fix up the current pointer.
859 if(pCurrent == pList->Current)
861 pList->Current = pEntry->Next;
865 // Check the head pointer.
867 if(pList->Head == pEntry)
869 pList->Head = pEntry->Next;
873 // Check the tail pointer.
875 if(pList->Tail == pEntry)
877 pList->Tail = pEntry->Previous;
881 // Set the entry pointers.
883 pEntry->Next = 0;
884 pEntry->Previous = 0;
885 pList->NumberOfEntries--;
886 ASSERT(0 <= pList->NumberOfEntries);
887 return pEntry->Data;
891 //*****************************************************************************
892 // alListRemoveHead
893 //*****************************************************************************
894 // Removes the list entry at the head of the list. If this is the current
895 // item, the current item will equal the next item in the list.
897 ALlistEntry* alListRemoveHead
899 IN ALlist* pList
902 ALlistEntry* pCurrent = 0;
904 ASSERT(pList);
905 ASSERT(pList->Locked);
908 // Release the item from the list.
910 pCurrent = pList->Head;
911 if(!pCurrent)
913 return 0;
917 // Fix up the next item in the list.
919 if(pCurrent->Next)
921 pCurrent->Next->Previous = 0;
925 // Fix up the previous item in the list.
927 ASSERT(!pCurrent->Previous)
930 // Fix up the current pointer.
932 if(pCurrent == pList->Current)
934 pList->Current = pCurrent->Next;
938 // Check the head pointer.
940 pList->Head = pCurrent->Next;
943 // Check the tail pointer.
945 if(pList->Tail == pCurrent)
947 pList->Tail = 0;
951 // Set the entry pointers.
953 pCurrent->Next = 0;
954 pCurrent->Previous = 0;
955 pList->NumberOfEntries--;
956 ASSERT(0 <= pList->NumberOfEntries);
957 return pCurrent;
961 //*****************************************************************************
962 // alListRemoveTail
963 //*****************************************************************************
964 // Removes the list entry at the tail of the list. If this is the current
965 // item, the current item will be null.
967 ALlistEntry* alListRemoveTail
969 IN ALlist* pList
972 ALlistEntry* pCurrent = 0;
974 ASSERT(pList);
975 ASSERT(pList->Locked);
978 // Release the item from the list.
980 pCurrent = pList->Tail;
981 if(!pCurrent)
983 return 0;
987 // Fix up the next item in the list.
989 ASSERT(!pCurrent->Next)
992 // Fix up the previous item in the list.
994 if(pCurrent->Previous)
996 pCurrent->Previous->Next = 0;
1000 // Fix up the current pointer.
1002 if(pCurrent == pList->Current)
1004 pList->Current = 0;
1008 // Check the head pointer.
1010 if(pList->Head == pCurrent)
1012 pList->Head = 0;
1016 // Check the tail pointer.
1018 pList->Tail = pCurrent->Previous;
1021 // Set the entry pointers.
1023 pCurrent->Next = 0;
1024 pCurrent->Previous = 0;
1025 pList->NumberOfEntries--;
1026 ASSERT(0 <= pList->NumberOfEntries);
1027 return pCurrent;