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
30 //****************************************************************************
31 //****************************************************************************
35 //****************************************************************************
36 //****************************************************************************
39 // Some occasionally useful debugging stuff.
43 static ALint alListDebugAssertsEnabled
= 1;
46 if(!(exp) && alListDebugAssertsEnabled) \
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) \
70 //****************************************************************************
71 //****************************************************************************
75 //****************************************************************************
76 //****************************************************************************
78 //*****************************************************************************
80 //*****************************************************************************
81 // Adds an entry to the tail of the list. Each entry must be unique.
86 IN ALlistEntry
* pEntry
90 ALlistEntry
* pCurrent
= 0;
95 ASSERT(pList
->Locked
);
96 ASSERT(!pEntry
->Next
);
97 ASSERT(!pEntry
->Previous
);
100 // Verify the entry doesn't already exist.
103 pCurrent
= pList
->Head
;
106 if(pCurrent
== pEntry
)
111 pCurrent
= pCurrent
->Next
;
116 // Duplicate entries are not supported.
124 // Add the item to the tail of the list.
128 pList
->Tail
->Next
= pEntry
;
131 pEntry
->Previous
= pList
->Tail
;
132 pList
->Tail
= pEntry
;
135 // Check if this is the first entry.
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
155 IN ALlistEntry
* pEntry
159 ALlistEntry
* pCurrent
= 0;
163 ASSERT(pList
->Locked
);
164 ASSERT(!pEntry
->Next
);
165 ASSERT(!pEntry
->Previous
);
168 // Verify the entry doesn't already exist.
171 pCurrent
= pList
->Head
;
174 if(pCurrent
== pEntry
)
179 pCurrent
= pCurrent
->Next
;
184 // Duplicate entries are not supported.
192 // Add the item to the head of the list.
196 pList
->Head
->Previous
= pEntry
;
199 pEntry
->Next
= pList
->Head
;
200 pList
->Head
= pEntry
;
203 // Check if this is the first entry.
207 pList
->Tail
= pEntry
;
208 pList
->Current
= pEntry
;
211 pList
->NumberOfEntries
++;
215 //*****************************************************************************
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
228 EnterCriticalSection(&pList
->Lock
);
234 // Check that only one person has the lock.
236 ASSERT(pList
->Locked
== 1);
240 //*****************************************************************************
242 //*****************************************************************************
243 // Creates and initializes a list.
245 ALboolean alListCreate
255 // Allocate and initialize the list context.
258 pList
= (ALlist
*)malloc(sizeof(ALlist
));
261 // Failed to allocate the list!
266 memset(pList
, 0, sizeof(ALlist
));
267 InitializeCriticalSection(&pList
->Lock
);
268 pList
->NumberOfEntries
= 0;
274 //*****************************************************************************
276 //*****************************************************************************
277 // Destroys the list.
285 ASSERT(!pList
->Head
);
288 // Free the resources allocated during the creation.
292 DeleteCriticalSection(&pList
->Lock
);
300 //*****************************************************************************
302 //*****************************************************************************
303 // Returns the data from the list entry.
305 ALvoid
* alListGetData
307 IN ALlistEntry
* pEntry
316 //*****************************************************************************
318 //*****************************************************************************
319 // Returns the entry in the list at the specified index of the list.
321 ALlistEntry
* alListGetEntryAt
327 ALlistEntry
* pEntry
= 0;
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
;
344 //*****************************************************************************
345 // alListGetEntryCount
346 //*****************************************************************************
347 // Returns the number of items stored in the list.
349 ALint alListGetEntryCount
354 ASSERT(pList
->Locked
);
355 return pList
->NumberOfEntries
;
359 //*****************************************************************************
361 //*****************************************************************************
362 // Returns the first entry in the list.
364 ALlistEntry
* alListGetHead
370 ASSERT(pList
->Locked
);
376 //*****************************************************************************
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
389 ASSERT(pList
->Locked
);
396 return pList
->Current
->Next
;
400 //*****************************************************************************
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
412 ASSERT(pList
->Locked
);
419 return pList
->Current
->Previous
;
423 //*****************************************************************************
425 //*****************************************************************************
426 // Returns the last entry in the list.
428 ALlistEntry
* alListGetTail
434 ASSERT(pList
->Locked
);
440 //*****************************************************************************
441 // alListInitializeEntry
442 //*****************************************************************************
443 // Initializes a preallocated list entry.
445 ALvoid alListInitializeEntry
453 pEntry
->Data
= pData
;
455 pEntry
->Previous
= 0;
459 //*****************************************************************************
461 //*****************************************************************************
462 // Returns the TRUE if the list is empty.
464 ALboolean alListIsEmpty
470 ASSERT(pList
->Locked
);
472 return (pList
->Head
== 0);
476 //*****************************************************************************
478 //*****************************************************************************
479 // Returns the entry pointed to by the iterator.
481 ALlistEntry
* alListIteratorGet
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
505 ALlistEntry
* pCurrent
= 0;
508 ASSERT(pList
->Locked
);
513 pCurrent
= pList
->Head
;
516 if(pCurrent
->Data
== pData
)
521 pCurrent
= pCurrent
->Next
;
524 pList
->Current
= 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
541 ASSERT(pList
->Locked
);
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
565 ASSERT(pList
->Locked
);
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
588 ALlistEntry
* pEntry
= 0;
591 ASSERT(pList
->Locked
);
594 // Make sure we aren't at the end of the list.
602 // Remove the item from the list.
604 pEntry
= pList
->Current
;
607 // Fix up the next item in the list.
611 pEntry
->Next
->Previous
= pEntry
->Previous
;
615 // Fix up the previous item in the list.
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.
647 pEntry
->Previous
= 0;
648 pList
->NumberOfEntries
--;
649 ASSERT(0 <= pList
->NumberOfEntries
);
654 //*****************************************************************************
655 // alListIteratorReset
656 //*****************************************************************************
657 // Returns the list iterator to the head of the list.
659 ALlistEntry
* alListIteratorReset
665 ASSERT(pList
->Locked
);
667 pList
->Current
= pList
->Head
;
668 return pList
->Current
;
672 //*****************************************************************************
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
681 IN ALlistEntry
* pEntry
684 ALlistEntry
* pCurrent
= 0;
687 ASSERT(pList
->Locked
);
689 pCurrent
= pList
->Head
;
692 if(pCurrent
== pEntry
)
697 pCurrent
= pCurrent
->Next
;
700 pList
->Current
= pCurrent
;
701 return pList
->Current
;
705 //*****************************************************************************
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
714 IN ALlistEntry
* pEntry
717 ALlistEntry
* pCurrent
= 0;
720 ASSERT(pList
->Locked
);
725 pCurrent
= pList
->Head
;
728 if(pCurrent
== pEntry
)
733 pCurrent
= pCurrent
->Next
;
741 return pCurrent
->Data
;
745 //*****************************************************************************
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
757 ALlistEntry
* pCurrent
= 0;
760 ASSERT(pList
->Locked
);
765 pCurrent
= pList
->Head
;
768 if(pCurrent
->Data
== pData
)
773 pCurrent
= pCurrent
->Next
;
780 //*****************************************************************************
782 //*****************************************************************************
783 // This is called to release the list lock.
785 ALvoid alListReleaseLock
791 ASSERT(pList
->Locked
);
795 ASSERT(pList
->Locked
== 0);
798 LeaveCriticalSection(&pList
->Lock
);
802 //*****************************************************************************
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
809 ALvoid
* alListRemoveEntry
812 IN ALlistEntry
* pEntry
815 ALlistEntry
* pCurrent
= 0;
818 ASSERT(pList
->Locked
);
822 // Release the item from the list.
824 pCurrent
= pList
->Head
;
827 if(pCurrent
== pEntry
)
832 pCurrent
= pCurrent
->Next
;
841 // Fix up the next item in the list.
845 pEntry
->Next
->Previous
= pEntry
->Previous
;
849 // Fix up the previous item in the list.
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.
884 pEntry
->Previous
= 0;
885 pList
->NumberOfEntries
--;
886 ASSERT(0 <= pList
->NumberOfEntries
);
891 //*****************************************************************************
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
902 ALlistEntry
* pCurrent
= 0;
905 ASSERT(pList
->Locked
);
908 // Release the item from the list.
910 pCurrent
= pList
->Head
;
917 // Fix up the next item in the list.
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
)
951 // Set the entry pointers.
954 pCurrent
->Previous
= 0;
955 pList
->NumberOfEntries
--;
956 ASSERT(0 <= pList
->NumberOfEntries
);
961 //*****************************************************************************
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
972 ALlistEntry
* pCurrent
= 0;
975 ASSERT(pList
->Locked
);
978 // Release the item from the list.
980 pCurrent
= pList
->Tail
;
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
)
1008 // Check the head pointer.
1010 if(pList
->Head
== pCurrent
)
1016 // Check the tail pointer.
1018 pList
->Tail
= pCurrent
->Previous
;
1021 // Set the entry pointers.
1024 pCurrent
->Previous
= 0;
1025 pList
->NumberOfEntries
--;
1026 ASSERT(0 <= pList
->NumberOfEntries
);