2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 A doubly linked list template.
34 // A Link can be a node in a list or a list itself.
40 Link() : mNext(this), mPrev(this) {}
42 T
* Prev() { return static_cast<T
*>(mPrev
); }
43 T
* Next() { return static_cast<T
*>(mNext
); }
45 void RemoveLeaveDangling()
53 RemoveLeaveDangling();
57 void InsertAfter(T
*inLink
)
60 mNext
= inLink
->mNext
;
65 void InsertBefore(T
*inLink
)
68 mPrev
= inLink
->mPrev
;
73 T
* Head() { return static_cast<T
*>(mNext
); }
74 T
* Tail() { return static_cast<T
*>(mPrev
); }
78 void PushHead(T
* inBuf
);
79 void PushTail(T
* inBuf
);
81 bool ContainsBuf(T
* inBuf
);
82 bool IsEmpty() { return mNext
== this; }
83 void BeEmpty() { mNext
= mPrev
= this; }
91 // Codewarrior refuses to inline Next() in some places..
92 Link
<T
> *mNext
, *mPrev
;
95 template <class T
, class Alloc
>
96 void MakeListEmpty(Link
<T
> *inLink
, Alloc
* inAlloc
)
98 Link
<T
>* link
= inLink
->mNext
;
99 while (link
!= inLink
) {
100 Link
<T
>* nextlink
= link
->mNext
;
101 // SC uses placement new extensively, so here we do a 'placement delete'.
102 // Using DestructSelf allows me to have either virtual
103 // or non virtual destructors in subclasses at the discretion of the subclass.
104 ((T
*)(link
))->DestructSelf();
105 inAlloc
->Free(static_cast<T
*>(link
));
108 inLink
->mNext
= inLink
->mPrev
= inLink
;
112 void Link
<T
>::PushHead(T
* inLink
)
114 assert(SanityCheck());
116 Link
<T
>* link
= static_cast<Link
<T
>*>(inLink
);
117 link
->InsertAfter(static_cast<T
*>(this));
119 assert(SanityCheck());
123 T
* Link
<T
>::PopHead()
125 assert(SanityCheck());
126 if (IsEmpty()) return 0;
128 Link
<T
>* link
= mNext
;
132 assert(SanityCheck());
133 return static_cast<T
*>(link
);
137 void Link
<T
>::PushTail(T
* inLink
)
139 assert(SanityCheck());
141 Link
<T
>* link
= static_cast<Link
<T
>*>(inLink
);
142 link
->InsertBefore(static_cast<T
*>(this));
144 assert(SanityCheck());
148 T
* Link
<T
>::PopTail()
150 assert(SanityCheck());
151 if (IsEmpty()) return 0;
153 Link
<T
>* link
= mPrev
;
156 assert(SanityCheck());
157 return static_cast<T
*>(link
);
161 void Link
<T
>::Cat(T
* inLink
)
163 assert(SanityCheck());
165 Link
<T
>* link
= static_cast<Link
<T
>*>(inLink
);
167 if (link
->IsEmpty()) return;
171 link
->mNext
->mPrev
= this;
172 link
->mPrev
->mNext
= this;
174 link
->mNext
->mPrev
= mPrev
;
175 link
->mPrev
->mNext
= this;
176 mPrev
->mNext
= link
->mNext
;
182 assert(SanityCheck());
186 bool Link
<T
>::ContainsBuf(T
* inLink
)
188 Link
<T
>* link
= static_cast<Link
<T
>*>(inLink
);
189 Link
<T
>* curLink
= mNext
;
190 while (curLink
!= this) {
191 if (curLink
== link
) return true;
192 curLink
= curLink
->mNext
;
198 void Link
<T
>::DebugDump()
200 Link
<T
>* link
= mNext
;
201 while (link
!= this) {
202 //post("Link-> %08X next %08X prev %08X\n",
203 // link, link->mNext, link->mPrev);
209 bool Link
<T
>::SanityCheck()
211 Link
<T
>* link
= mNext
;
212 while (link
!= this) {
213 if (link
->mPrev
->mNext
!= link
) {
214 throw std::runtime_error("Link: bad link <-,->");
216 if (link
->mNext
->mPrev
!= link
) {
217 throw std::runtime_error("Link: bad link ->,<-");