1
/*************************************************************************
2
This software is part of a public domain IronDoc source code distribution,
3
and is provided on an "AS IS" basis, with all risks borne by the consumers
4
or users of the IronDoc software. There are no warranties, guarantees, or
5
promises about quality of any kind; and no remedies for failure exist.
7
Permission is hereby granted to use this IronDoc software for any purpose
8
at all, without need for written agreements, without royalty or license
9
fees, and without fees or obligations of any other kind. Anyone can use,
10
copy, change and distribute this software for any purpose, and nothing is
11
required, implicitly or otherwise, in exchange for this usage.
13
You cannot apply your own copyright to this software, but otherwise you
14
are encouraged to enjoy the use of this software in any way you see fit.
15
However, it would be rude to remove names of developers from the code.
16
(IronDoc is also known by the short name "Fe" and a longer name "Ferrum",
17
which are used interchangeably with the name IronDoc in the sources.)
18
*************************************************************************/
21
* Contains: Ferrum deque (double ended queue (linked list))
23
* Copied directly from public domain IronDoc, with minor naming tweaks:
24
* Designed and written by David McCusker, but all this code is public domain.
25
* There are no warranties, no guarantees, no promises, and no remedies.
35
/*=============================================================================
36
* morkNext: linked list node for very simple, singly-linked list
39
class morkNext /*d*/ {
44
morkNext(int inZero) : mNext_Link( 0 ) { }
46
morkNext(morkNext* ioLink) : mNext_Link( ioLink ) { }
48
morkNext(); // mNext_Link( 0 ), { }
51
morkNext* GetNextLink() const { return mNext_Link; }
53
public: // link memory management methods
54
static void* MakeNewNext(size_t inSize, nsIMdbHeap& ioHeap, morkEnv* ev);
55
void ZapOldNext(morkEnv* ev, nsIMdbHeap* ioHeap);
57
public: // link memory management operators
58
void* operator new(size_t inSize, nsIMdbHeap& ioHeap, morkEnv* ev) CPP_THROW_NEW
59
{ return morkNext::MakeNewNext(inSize, ioHeap, ev); }
61
void operator delete(void* ioAddress) // DO NOT CALL THIS, hope to crash:
62
{ ((morkNext*) 0)->ZapOldNext((morkEnv*) 0, (nsIMdbHeap*) 0); } // boom
65
/*=============================================================================
66
* morkList: simple, singly-linked list
69
/*| morkList: a list of singly-linked members (instances of morkNext), where
70
**| the number of list members might be so numerous that we must about cost
71
**| for two pointer link slots per member (as happens with morkLink).
73
**|| morkList is intended to support lists of changes in morkTable, where we
74
**| are worried about the space cost of representing such changes. (Later we
75
**| can use an array instead, when we get even more worried, to avoid cost
76
**| of link slots at all, per member).
78
**|| Do NOT create cycles in links using this list class, since we do not
79
**| deal with them very nicely.
81
class morkList /*d*/ {
83
morkNext* mList_Head; // first link in the list
84
morkNext* mList_Tail; // last link in the list
87
morkNext* GetListHead() const { return mList_Head; }
88
morkNext* GetListTail() const { return mList_Tail; }
90
mork_bool IsListEmpty() const { return ( mList_Head == 0 ); }
91
mork_bool HasListMembers() const { return ( mList_Head != 0 ); }
94
morkList(); // : mList_Head( 0 ), mList_Tail( 0 ) { }
96
void CutAndZapAllListMembers(morkEnv* ev, nsIMdbHeap* ioHeap);
97
// make empty list, zapping every member by calling ZapOldNext()
99
void CutAllListMembers();
100
// just make list empty, dropping members without zapping
103
morkNext* PopHead(); // cut head of list
105
// Note we don't support PopTail(), so use morkDeque if you need that.
107
void PushHead(morkNext* ioLink); // add to head of list
108
void PushTail(morkNext* ioLink); // add to tail of list
111
/*=============================================================================
112
* morkLink: linked list node embedded in objs to allow insertion in morkDeques
115
class morkLink /*d*/ {
117
morkLink* mLink_Next;
118
morkLink* mLink_Prev;
121
morkLink(int inZero) : mLink_Next( 0 ), mLink_Prev( 0 ) { }
123
morkLink(); // mLink_Next( 0 ), mLink_Prev( 0 ) { }
126
morkLink* Next() const { return mLink_Next; }
127
morkLink* Prev() const { return mLink_Prev; }
129
void SelfRefer() { mLink_Next = mLink_Prev = this; }
130
void Clear() { mLink_Next = mLink_Prev = 0; }
132
void AddBefore(morkLink* old)
134
((old)->mLink_Prev->mLink_Next = (this))->mLink_Prev = (old)->mLink_Prev;
135
((this)->mLink_Next = (old))->mLink_Prev = this;
138
void AddAfter(morkLink* old)
140
((old)->mLink_Next->mLink_Prev = (this))->mLink_Next = (old)->mLink_Next;
141
((this)->mLink_Prev = (old))->mLink_Next = this;
146
(mLink_Prev->mLink_Next = mLink_Next)->mLink_Prev = mLink_Prev;
149
public: // link memory management methods
150
static void* MakeNewLink(size_t inSize, nsIMdbHeap& ioHeap, morkEnv* ev);
151
void ZapOldLink(morkEnv* ev, nsIMdbHeap* ioHeap);
153
public: // link memory management operators
154
void* operator new(size_t inSize, nsIMdbHeap& ioHeap, morkEnv* ev) CPP_THROW_NEW
155
{ return morkLink::MakeNewLink(inSize, ioHeap, ev); }
159
/*=============================================================================
160
* morkDeque: doubly linked list modeled after VAX queue instructions
163
class morkDeque /*d*/ {
165
morkLink mDeque_Head;
167
public: // construction
168
morkDeque(); // { mDeque_Head.SelfRefer(); }
171
morkLink* RemoveFirst();
173
morkLink* RemoveLast();
175
morkLink* At(mork_pos index) const ; /* one-based, not zero-based */
177
mork_pos IndexOf(const morkLink* inMember) const;
178
/* one-based index ; zero means member is not in deque */
180
mork_num Length() const;
182
/* the following method is more efficient for long lists: */
183
int LengthCompare(mork_num inCount) const;
184
/* -1: length < count, 0: length == count, 1: length > count */
188
mork_bool IsEmpty()const
189
{ return (mDeque_Head.mLink_Next == (morkLink*) &mDeque_Head); }
191
morkLink* After(const morkLink* old) const
192
{ return (((old)->mLink_Next != &mDeque_Head)?
193
(old)->mLink_Next : (morkLink*) 0); }
195
morkLink* Before(const morkLink* old) const
196
{ return (((old)->mLink_Prev != &mDeque_Head)?
197
(old)->mLink_Prev : (morkLink*) 0); }
199
morkLink* First() const
200
{ return ((mDeque_Head.mLink_Next != &mDeque_Head)?
201
mDeque_Head.mLink_Next : (morkLink*) 0); }
203
morkLink* Last() const
204
{ return ((mDeque_Head.mLink_Prev != &mDeque_Head)?
205
mDeque_Head.mLink_Prev : (morkLink*) 0); }
208
From IronDoc documentation for AddFirst:
209
+--------+ +--------+ +--------+ +--------+ +--------+
210
| h.next |-->| b.next | | h.next |-->| a.next |-->| b.next |
211
+--------+ +--------+ ==> +--------+ +--------+ +--------+
212
| h.prev |<--| b.prev | | h.prev |<--| a.prev |<--| b.prev |
213
+--------+ +--------+ +--------+ +--------+ +--------+
216
void AddFirst(morkLink* in) /*i*/
218
( (mDeque_Head.mLink_Next->mLink_Prev =
219
(in))->mLink_Next = mDeque_Head.mLink_Next,
220
((in)->mLink_Prev = &mDeque_Head)->mLink_Next = (in) );
223
From IronDoc documentation for AddLast:
224
+--------+ +--------+ +--------+ +--------+ +--------+
225
| y.next |-->| h.next | | y.next |-->| z.next |-->| h.next |
226
+--------+ +--------+ ==> +--------+ +--------+ +--------+
227
| y.prev |<--| h.prev | | y.prev |<--| z.prev |<--| h.prev |
228
+--------+ +--------+ +--------+ +--------+ +--------+
231
void AddLast(morkLink* in)
233
( (mDeque_Head.mLink_Prev->mLink_Next =
234
(in))->mLink_Prev = mDeque_Head.mLink_Prev,
235
((in)->mLink_Next = &mDeque_Head)->mLink_Prev = (in) );
239
#endif /* _MORKDEQUE_ */