1 //------------------------------------------------------------------------------
2 // emList.h
3 //
4 // Copyright (C) 2005-2010,2014-2015 Oliver Hamann.
5 //
6 // Homepage: http://eaglemode.sourceforge.net/
7 //
8 // This program is free software: you can redistribute it and/or modify it under
9 // the terms of the GNU General Public License version 3 as published by the
10 // Free Software Foundation.
11 //
12 // This program is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for
15 // more details.
16 //
17 // You should have received a copy of the GNU General Public License version 3
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 //------------------------------------------------------------------------------
20 
21 #ifndef emList_h
22 #define emList_h
23 
24 #ifndef emStd1_h
25 #include <emCore/emStd1.h>
26 #endif
27 
28 
29 //==============================================================================
30 //=========================== Linked-list functions ============================
31 //==============================================================================
32 
33 bool emSortSingleLinkedList(
34 	void * * pFirst, int nextOffset,
35 	int(*compare)(void * ptr1, void * ptr2, void * context),
36 	void * context=NULL
37 );
38 	// Sort a single-linked NULL-terminated list. The order of equal
39 	// elements is preserved. It is a merge-sort algorithm.
40 	// Arguments:
41 	//   pFirst     - Pointer to pointer to first element. On return,
42 	//                *pFirst will be set to the new first element.
43 	//   nextOffset - Offset where the pointer to the next element is stored
44 	//                within an element: If e points to an element, then
45 	//                *((void**)(((char*)e)+nextOffset)) points to the next
46 	//                element.
47 	//   compare    - Function for comparing two elements. If you want the
48 	//                elements to be compared via the operators '<' and '>',
49 	//                say:
50 	//                  emStdComparer<OBJ>::Compare
51 	//                with OBJ replaced by the real type of the elements.
52 	//                The context argument is ignored then.
53 	//                Arguments:
54 	//                  ptr1    - Pointer to first element.
55 	//                  ptr2    - Pointer to second element.
56 	//                  context - See below.
57 	//                Returns: Zero if the elements are equal, a value
58 	//                  greater than zero if the first element is greater
59 	//                  than the second one, and a value less than zero if
60 	//                  the first element is less than the second one.
61 	//   context    - Any pointer to be forwarded to the compare function.
62 	// Returns: true if the order has changed, false otherwise.
63 
64 bool emSortDoubleLinkedList(
65 	void * * pFirst, void * * pLast, int nextOffset, int prevOffset,
66 	int(*compare)(void * ptr1, void * ptr2, void * context),
67 	void * context=NULL
68 );
69 	// Sort a double-linked NULL-terminated list. The order of equal
70 	// elements is preserved. It is a merge-sort algorithm.
71 	// Arguments:
72 	//   pFirst     - Pointer to pointer to first element. On return,
73 	//                *pFirst will be set to the new first element.
74 	//   pLast      - Pointer to pointer to last element. On return, *pLast
75 	//                will be set to the new last element.
76 	//   nextOffset - Offset where the pointer to the next element is stored
77 	//                within an element: If e points to an element, then
78 	//                *((void**)(((char*)e)+nextOffset)) points to the next
79 	//                element.
80 	//   prevOffset - Offset where the pointer to the previous element is
81 	//                stored within an element: If e points to an element,
82 	//                then *((void**)(((char*)e)+prevOffset)) points to
83 	//                the previous element.
84 	//   compare    - Function for comparing two elements. If you want the
85 	//                elements to be compared via the operators '<' and '>',
86 	//                say:
87 	//                  emStdComparer<OBJ>::Compare
88 	//                with OBJ replaced by the real type of the elements.
89 	//                The context argument is ignored then.
90 	//                Arguments:
91 	//                  ptr1    - Pointer to first element.
92 	//                  ptr2    - Pointer to second element.
93 	//                  context - See below.
94 	//                Returns: Zero if the elements are equal, a value
95 	//                  greater than zero if the first element is greater
96 	//                  than the second one, and a value less than zero if
97 	//                  the first element is less than the second one.
98 	//   context    - Any pointer to be forwarded to the compare function.
99 	// Returns: true if the order has changed, false otherwise.
100 
101 
102 //==============================================================================
103 //=================================== emList ===================================
104 //==============================================================================
105 
106 template <class OBJ> class emList {
107 
108 public:
109 
110 	// Template class for a double-linked NULL-terminated list with
111 	// copy-on-write behavior and with support for stable iterators. The
112 	// template parameter OBJ describes the type of the elements.
113 	// Internally, emList extends the memory allocation for that type by the
114 	// next and prev pointers.
115 	//
116 	// There are two types of iterators. The very unstable one:
117 	// const OBJ * (please read the comments on GetFirst()), and the
118 	// stable one: the class Iterator, which can be found at the end of this
119 	// public declaration.
120 	//
121 	// If you wonder why a NULL in range arguments (first,last) of methods
122 	// means to cancel the operation, instead of taking the first/last
123 	// element of the whole list. It is because now one can say for example
124 	// l.Remove(l.GetNext(e),l.GetLast()) to remove all elements after the
125 	// element e, even when e is the last element.
126 	//
127 	// Here is a crazy example of printing "hello world\n":
128 	//
129 	// emList<emString> l;
130 	// emList<emString>::Iterator i;
131 	// const emString * j;
132 	// l="word";
133 	// l+="helo";
134 	// for (i.SetFirst(l); i; ++i) l.GetWritable(i)->Insert(3,'l');
135 	// l.Sort(emStdComparer<emString>::Compare);
136 	// for (i.SetLast(l); i; --i) l.InsertAfter(i," ");
137 	// *l.GetLastWritable()="\n";
138 	// // The following loop does not modify the list, so it is safe
139 	// // to do it with the unstable iterator j.
140 	// for (j=l.GetFirst(); j; j=l.GetNext(j)) printf("%s",j->Get());
141 
142 	emList();
143 		// Construct an empty list.
144 
145 	emList(const emList & src);
146 		// Construct a copied list.
147 
148 	emList(const OBJ & obj);
149 		// Construct a list with one element copied from the given
150 		// object.
151 
152 	emList(const emList & src1, const emList & src2);
153 	emList(const emList & src1, const OBJ & src2);
154 	emList(const OBJ & src1, const emList & src2);
155 	emList(const emList & src, const OBJ * first, const OBJ * last);
156 		// These constructors are designed mainly for internal use.
157 
158 	~emList();
159 		// Destructor.
160 
161 	emList & operator = (const emList & list);
162 	emList & operator = (const OBJ & obj);
163 		// Make this list a copy of the given list or object.
164 
165 	const OBJ * GetFirst() const;
166 	const OBJ * GetLast() const;
167 	const OBJ * GetNext(const OBJ * elem) const;
168 	const OBJ * GetPrev(const OBJ * elem) const;
169 		// Get a pointer to the first or last element of this list, or
170 		// get a pointer to the next or previous element of an element
171 		// of this list. At least because of the copy-on-write feature,
172 		// the pointer is valid only until calling any non-const method
173 		// or operator on this list, or giving this list as a non-const
174 		// argument to any call in the world. If you need more stable
175 		// pointers, please refer to the class Iterator more below.
176 		// Hint: even methods like Add, Insert and GetSubList may make
177 		// shallow copies, like the copy operator and copy constructor
178 		// do.
179 		// Arguments:
180 		//   elem - A pointer to an element in this list, must never be
181 		//          NULL.
182 		// Returns:
183 		//   A pointer to the requested element in this list, or NULL if
184 		//   there is no such element.
185 
186 	OBJ * GetWritable(const OBJ * elem);
187 		// Get a non-const version of a pointer to an element of this
188 		// list. The pointer may be used for modifying the element (but
189 		// not for deleting). The rules for validity of the pointer are
190 		// the same as with the GetFirst() method, but: The pointer must
191 		// not be used for modifying after doing something which could
192 		// have made a shallow copy of this list.
193 		// Arguments:
194 		//   elem - A pointer to an element of this list, or NULL.
195 		// Returns: Pointer for modifying, or NULL if elem is NULL.
196 
197 	OBJ * GetFirstWritable();
198 	OBJ * GetLastWritable();
199 	OBJ * GetNextWritable(const OBJ * elem);
200 	OBJ * GetPrevWritable(const OBJ * elem);
201 		// Like GetWritable(GetFirst()) and so on.
202 
203 	void Set(const OBJ * pos, const OBJ & obj);
204 		// Replace an element.
205 		// Arguments:
206 		//   pos - A pointer to an element of this list.
207 		//   obj - An object to be copied to the element.
208 
209 	void InsertAtBeg(const OBJ & obj);
210 	void InsertAtBeg(const OBJ * elem);
211 	void InsertAtBeg(const OBJ * first, const OBJ * last);
212 	void InsertAtBeg(const emList & src);
213 	void InsertAtBeg(const emList & src, const OBJ * elem);
214 	void InsertAtBeg(const emList & src, const OBJ * first,
215 	                 const OBJ * last);
216 	void InsertAtEnd(const OBJ & obj);
217 	void InsertAtEnd(const OBJ * elem);
218 	void InsertAtEnd(const OBJ * first, const OBJ * last);
219 	void InsertAtEnd(const emList & src);
220 	void InsertAtEnd(const emList & src, const OBJ * elem);
221 	void InsertAtEnd(const emList & src, const OBJ * first,
222 	                 const OBJ * last);
223 	void InsertBefore(const OBJ * pos, const OBJ & obj);
224 	void InsertBefore(const OBJ * pos, const OBJ * elem);
225 	void InsertBefore(const OBJ * pos, const OBJ * first, const OBJ * last);
226 	void InsertBefore(const OBJ * pos, const emList & src);
227 	void InsertBefore(const OBJ * pos, const emList & src,
228 	                  const OBJ * elem);
229 	void InsertBefore(const OBJ * pos, const emList & src,
230 	                  const OBJ * first, const OBJ * last);
231 	void InsertAfter(const OBJ * pos, const OBJ & obj);
232 	void InsertAfter(const OBJ * pos, const OBJ * elem);
233 	void InsertAfter(const OBJ * pos, const OBJ * first, const OBJ * last);
234 	void InsertAfter(const OBJ * pos, const emList & src);
235 	void InsertAfter(const OBJ * pos, const emList & src, const OBJ * elem);
236 	void InsertAfter(const OBJ * pos, const emList & src, const OBJ * first,
237 	                 const OBJ * last);
238 		// Insert elements at the beginning or end of this list, or
239 		// before or after an element of this list. It is even allowed
240 		// to insert a list into itself.
241 		// Arguments:
242 		//   pos   - An element in this list before which or after which
243 		//           the insertion has to take place. NULL is allowed
244 		//           here. InsertBefore(NULL,...) means to insert at the
245 		//           end, and InsertAfter(NULL,...) means to insert at
246 		//           the beginning.
247 		//   obj   - An object to be copied for inserting a single
248 		//           element.
249 		//   src   - A source list containing the element(s) to be
250 		//           copied for the insertion. If this argument is not
251 		//           given, this list itself is the source list.
252 		//   elem  - An element of the source list. The element is
253 		//           copied for inserting a single element. If NULL,
254 		//           nothing is inserted.
255 		//   first - An element of the source list. It is the first one
256 		//           of a range of elements to be copied for the
257 		//           insertion. If NULL, nothing is inserted.
258 		//   last  - An element of the source list, not before 'first'.
259 		//           It is the last one of the range of elements to be
260 		//           copied for the insertion. If NULL, nothing is
261 		//           inserted.
262 
263 	void Add(const OBJ & obj);
264 	void Add(const OBJ * elem);
265 	void Add(const OBJ * first, const OBJ * last);
266 	void Add(const emList & src);
267 	void Add(const emList & src, const OBJ * elem);
268 	void Add(const emList & src, const OBJ * first, const OBJ * last);
269 		// Just another name for InsertAtEnd.
270 
271 	emList & operator += (const emList & list);
272 	emList & operator += (const OBJ & obj);
273 	emList operator + (const emList & list) const;
274 	emList operator + (const OBJ & obj) const;
275 		// Similar to the Add methods...
276 
277 	//friend emList operator + (const OBJ & obj, const emList & list);
278 		// This one even exists and can be used.
279 		// (Having the declaration here would not be portable)
280 
281 	void MoveToBeg(const OBJ * elem);
282 	void MoveToBeg(const OBJ * first, const OBJ * last);
283 	void MoveToBeg(emList * src);
284 	void MoveToBeg(emList * src, const OBJ * elem);
285 	void MoveToBeg(emList * src, const OBJ * first, const OBJ * last);
286 	void MoveToEnd(const OBJ * elem);
287 	void MoveToEnd(const OBJ * first, const OBJ * last);
288 	void MoveToEnd(emList * src);
289 	void MoveToEnd(emList * src, const OBJ * elem);
290 	void MoveToEnd(emList * src, const OBJ * first, const OBJ * last);
291 	void MoveBefore(const OBJ * pos, const OBJ * elem);
292 	void MoveBefore(const OBJ * pos, const OBJ * first, const OBJ * last);
293 	void MoveBefore(const OBJ * pos, emList * src);
294 	void MoveBefore(const OBJ * pos, emList * src, const OBJ * elem);
295 	void MoveBefore(const OBJ * pos, emList * src, const OBJ * first,
296 	                const OBJ * last);
297 	void MoveAfter(const OBJ * pos, const OBJ * elem);
298 	void MoveAfter(const OBJ * pos, const OBJ * first, const OBJ * last);
299 	void MoveAfter(const OBJ * pos, emList * src);
300 	void MoveAfter(const OBJ * pos, emList * src, const OBJ * elem);
301 	void MoveAfter(const OBJ * pos, emList * src, const OBJ * first,
302 	               const OBJ * last);
303 		// Move elements from a source list to the beginning or end of
304 		// this list, or before or after an element of this list.
305 		// Arguments:
306 		//   pos   - An element in this list before which or after which
307 		//           the elements are to be moved. It must not be a
308 		//           member of the moved elements! NULL is allowed here.
309 		//           MoveBefore(NULL,...) means to move to the end, and
310 		//           MoveAfter(NULL,...) means to move to the beginning.
311 		//   src   - Pointer to the source list. If NULL or not given,
312 		//           this list itself is the source list.
313 		//   elem  - An element of the source list, which shall be
314 		//           moved. If NULL, nothing is moved.
315 		//   first - An element of the source list. It is the first one
316 		//           of a range of elements to be moved. If NULL,
317 		//           nothing is moved.
318 		//   last  - An element of the source list, not before 'first'.
319 		//           It is the last one of the range of elements to be
320 		//           moved. If NULL, nothing is moved.
321 
322 	emList GetSubListOfFirst() const;
323 	emList GetSubListOfLast() const;
324 	emList GetSubList(const OBJ * elem) const;
325 	emList GetSubList(const OBJ * first, const OBJ * last) const;
326 		// Like the Extract methods (see below), but the elements are
327 		// copied instead of removing them from this list.
328 
329 	emList ExtractFirst();
330 	emList ExtractLast();
331 	emList Extract(const OBJ * elem);
332 	emList Extract(const OBJ * first, const OBJ * last);
333 		// Like the Remove methods (see below), but return a list of the
334 		// removed elements, instead of deleting them.
335 
336 	void RemoveFirst();
337 	void RemoveLast();
338 	void Remove(const OBJ * elem);
339 	void Remove(const OBJ * first, const OBJ * last);
340 		// Remove (and delete) the first element, the last element, a
341 		// given element or a range of elements from this list.
342 		// Arguments:
343 		//   elem  - An element of this list, which shall be removed.
344 		//           If NULL, nothing is removed.
345 		//   first - An element of this list. It is the first one of a
346 		//           range of elements to be removed. If NULL, nothing
347 		//           is removed.
348 		//   last  - An element of this list, not before 'first'. It is
349 		//           the last one of the range of elements to be
350 		//           removed. If NULL, nothing is removed.
351 
352 	void Clear(bool compact=false);
353 		// Remove (and delete) all elements of this list.
354 		// Arguments:
355 		//   compact - true if you plan to keep this list empty for
356 		//             a long time. Otherwise a small block of memory
357 		//             may possibly not be freed for quick re-use.
358 
359 	bool IsEmpty() const;
360 		// Ask whether this list has no elements.
361 
362 	bool Sort(
363 		int(*compare)(const OBJ * obj1, const OBJ * obj2,
364 		              void * context),
365 		void * context=NULL
366 	);
367 		// Sort this list. The order of equal elements is preserved.
368 		// Arguments:
369 		//   compare - Function for comparing two elements. If you want
370 		//             the elements to be compared via the operators '<'
371 		//             and '>', say:
372 		//               emStdComparer<OBJ>::Compare
373 		//             with OBJ replaced by the real type of the
374 		//             elements. The context argument is ignored then.
375 		//             Arguments:
376 		//               obj1    - Pointer to first element.
377 		//               obj2    - Pointer to second element.
378 		//               context - See below.
379 		//             Returns: Zero if the elements are equal, a value
380 		//               greater than zero if the first element is
381 		//               greater than the second one, and a value less
382 		//               than zero if the first element is less than the
383 		//               second one.
384 		//   context - Any pointer to be forwarded to the compare
385 		//             function.
386 		// Returns: Whether there was a change.
387 
388 	int GetCount() const;
389 		// Compute the number of elements.
390 
391 	const OBJ * GetAtIndex(int index) const;
392 		// Search the element at the given index. Returns NULL if the
393 		// index is out of range. The rules for the validity of the
394 		// pointer are the same as with the GetFirst() method.
395 
396 	int GetIndexOf(const OBJ * elem) const;
397 		// Search the given element and return its index. Returns -1
398 		// if it is not an element of this list.
399 
400 	unsigned int GetDataRefCount() const;
401 		// Get number of references to the data behind this list.
402 
403 	void MakeNonShared();
404 		// This must be called before handing the list to another
405 		// thread. This method is not recursive. So if the object class
406 		// even has such a method, you have to call it on every object
407 		// too.
408 
409 	class Iterator {
410 
411 	public:
412 
413 		// Class for a stable pointer to an element of a list.
414 		// "stable" means:
415 		// * If the address of an element changes through the
416 		//   copy-on-write mechanism, iterators pointing to that element
417 		//   are adapted proper.
418 		// * If an element is moved to another list, iterators pointing
419 		//   to that element keep pointing to that element (and the list
420 		//   pointers of the iterators are adapted).
421 		// * If an element is removed or extracted from a list,
422 		//   iterators pointing to that element are set to the next
423 		//   element, or NULL if it was the last element.
424 		// * If the assignment operator '=' is called on a list, all
425 		//   iterators which were pointing to elements of the list are
426 		//   set to NULL. This is even true if the list is assigned to
427 		//   itself.
428 		// Note the auto-cast operator to a 'const OBJ *'. Wherever
429 		// there is an argument 'const OBJ *' in the methods of emList,
430 		// you can even give an instance of this class as the argument.
431 
432 		Iterator();
433 			// Construct a "NULL pointer".
434 
435 		Iterator(const Iterator & iter);
436 			// Construct a copied iterator.
437 
438 		Iterator(const emList<OBJ> & list, const OBJ * elem);
439 			// Construct an iterator pointing to a particular
440 			// element.
441 			// Arguments:
442 			//   list - The list.
443 			//   elem - Pointer to an element of the list, or NULL.
444 
445 		~Iterator();
446 			// Destructor.
447 
448 		Iterator & operator = (const Iterator & iter);
449 			// Copy an iterator.
450 
451 		operator const OBJ * () const;
452 		const OBJ * operator * () const;
453 		const OBJ * operator -> () const;
454 		const OBJ * Get() const;
455 			// Get the element pointer. It is NULL if this iterator
456 			// does not point to any element.
457 
458 		const OBJ * Set(const Iterator & iter);
459 			// Copy the given iterator and return the element
460 			// pointer.
461 
462 		const OBJ * Set(const emList<OBJ> & list, const OBJ * elem);
463 			// Set this iterator to the given element of the given
464 			// list and return the element pointer.
465 
466 		const OBJ * SetFirst(const emList<OBJ> & list);
467 		const OBJ * SetLast(const emList<OBJ> & list);
468 			// Set this iterator to the first or last element of the
469 			// given list and return the element pointer.
470 
471 		const OBJ * SetNext();
472 		const OBJ * SetPrev();
473 		const OBJ * operator ++();
474 		const OBJ * operator --();
475 			// Set this iterator to the next or previous element and
476 			// return the new element pointer. This must be called
477 			// only if the old element pointer is not NULL.
478 
479 		const OBJ * operator ++(int);
480 		const OBJ * operator --(int);
481 			// Like above, but return the old element pointer.
482 
483 		bool operator == (const Iterator & iter) const;
484 		bool operator != (const Iterator & iter) const;
485 		bool operator == (const OBJ * elem) const;
486 		bool operator != (const OBJ * elem) const;
487 			// Ordinary compare operators.
488 
489 		const emList<OBJ> * GetList() const;
490 			// Get a pointer to the list this iterator is currently
491 			// attached to. Returns NULL if not attached to any
492 			// list. (See comments on Detach()).
493 
494 		void Detach();
495 			// Detach this iterator from its list and point to NULL.
496 			// Note: to care about the iterators, each emList has a
497 			// single linked list of its iterators. The mechanism is
498 			// lazy, that means, an iterator may stay in the list
499 			// even when not pointing to any element, just for quick
500 			// re-use. On the other hand, such iterators are still
501 			// costing a tiny number of CPU cycles whenever the list
502 			// of elements is modified.
503 
504 	private:
505 		friend class emList<OBJ>;
506 		const OBJ * Pos;
507 		emList<OBJ> * List;
508 		Iterator * NextIter; // Undefined if List==NULL
509 	};
510 
511 private:
512 	friend class Iterator;
513 
514 	struct Element {
515 		OBJ Obj;
516 		OBJ * Next;
517 		OBJ * Prev;
ElementElement518 		inline Element(const OBJ & obj) : Obj(obj) {}
519 	};
520 	struct SharedData {
521 		OBJ * First;
522 		OBJ * Last;
523 		bool IsStaticEmpty;
524 		unsigned int RefCount;
525 	};
526 
527 	SharedData * Data;
528 	Iterator * Iterators;
529 	static SharedData EmptyData;
530 
emList(SharedData * d)531 	inline emList(SharedData * d) { Data=d; Iterators=NULL; }
532 	void MakeWritable();
533 	void MakeWritable(const OBJ * * preserve);
534 	void MakeWritable(const OBJ * * preserve1, const OBJ * * preserve2);
535 	void MakeWritable(const OBJ * * preserve1, const OBJ * * preserve2,
536 	                  const OBJ * * preserve3);
537 	void DeleteData();
538 };
539 
540 
541 //==============================================================================
542 //============================== Implementations ===============================
543 //==============================================================================
544 
545 #define EM_LSTIMP_ELEM(objPtr) \
546 	((Element*)(((char*)(objPtr))-offsetof(Element,Obj)))
547 #define EM_LSTIMP_PREV(objPtr) EM_LSTIMP_ELEM(objPtr)->Prev
548 #define EM_LSTIMP_NEXT(objPtr) EM_LSTIMP_ELEM(objPtr)->Next
549 
emList()550 template <class OBJ> inline emList<OBJ>::emList()
551 {
552 	Iterators=NULL;
553 	Data=&EmptyData;
554 }
555 
emList(const emList & src)556 template <class OBJ> inline emList<OBJ>::emList(const emList & src)
557 {
558 	Iterators=NULL;
559 	Data=src.Data;
560 	Data->RefCount++;
561 }
562 
emList(const OBJ & obj)563 template <class OBJ> emList<OBJ>::emList(const OBJ & obj)
564 {
565 	Iterators=NULL;
566 	Data=&EmptyData;
567 	InsertBefore(NULL,obj);
568 }
569 
emList(const emList & src1,const emList & src2)570 template <class OBJ> emList<OBJ>::emList(
571 	const emList & src1, const emList & src2
572 )
573 {
574 	Iterators=NULL;
575 	Data=src1.Data;
576 	Data->RefCount++;
577 	InsertBefore(NULL,src2,src2.Data->First,src2.Data->Last);
578 }
579 
emList(const emList & src1,const OBJ & src2)580 template <class OBJ> emList<OBJ>::emList(
581 	const emList & src1, const OBJ & src2
582 )
583 {
584 	Iterators=NULL;
585 	Data=src1.Data;
586 	Data->RefCount++;
587 	InsertBefore(NULL,src2);
588 }
589 
emList(const OBJ & src1,const emList & src2)590 template <class OBJ> emList<OBJ>::emList(
591 	const OBJ & src1, const emList & src2
592 )
593 {
594 	Iterators=NULL;
595 	Data=src2.Data;
596 	Data->RefCount++;
597 	InsertAfter(NULL,src1);
598 }
599 
emList(const emList & src,const OBJ * first,const OBJ * last)600 template <class OBJ> emList<OBJ>::emList(
601 	const emList & src, const OBJ * first, const OBJ * last
602 )
603 {
604 	Iterators=NULL;
605 	Data=&EmptyData;
606 	InsertBefore(NULL,src,first,last);
607 }
608 
~emList()609 template <class OBJ> emList<OBJ>::~emList()
610 {
611 	Iterator * i;
612 
613 	for (i=Iterators; i; i=i->NextIter) { i->Pos=NULL; i->List=NULL; }
614 	if (!--Data->RefCount) DeleteData();
615 }
616 
617 template <class OBJ> emList<OBJ> & emList<OBJ>::operator = (
618 	const emList & list
619 )
620 {
621 	Iterator * i;
622 
623 	for (i=Iterators; i; i=i->NextIter) i->Pos=NULL;
624 	list.Data->RefCount++;
625 	if (!--Data->RefCount) DeleteData();
626 	Data=list.Data;
627 	return *this;
628 }
629 
630 template <class OBJ> emList<OBJ> & emList<OBJ>::operator = (const OBJ & obj)
631 {
632 	Iterator * i;
633 
634 	for (i=Iterators; i; i=i->NextIter) i->Pos=NULL;
635 	if (Data->RefCount>1) {
636 		Data->RefCount--;
637 		Data=&EmptyData;
638 	}
639 	InsertBefore(NULL,obj);
640 	if (EM_LSTIMP_PREV(Data->Last)) {
641 		Remove(Data->First,EM_LSTIMP_PREV(Data->Last));
642 	}
643 	return *this;
644 }
645 
GetFirst()646 template <class OBJ> inline const OBJ * emList<OBJ>::GetFirst() const
647 {
648 	return Data->First;
649 }
650 
GetLast()651 template <class OBJ> inline const OBJ * emList<OBJ>::GetLast() const
652 {
653 	return Data->Last;
654 }
655 
GetNext(const OBJ * elem)656 template <class OBJ> inline const OBJ * emList<OBJ>::GetNext(
657 	const OBJ * elem
658 ) const
659 {
660 	return EM_LSTIMP_NEXT(elem);
661 }
662 
GetPrev(const OBJ * elem)663 template <class OBJ> inline const OBJ * emList<OBJ>::GetPrev(
664 	const OBJ * elem
665 ) const
666 {
667 	return EM_LSTIMP_PREV(elem);
668 }
669 
GetWritable(const OBJ * elem)670 template <class OBJ> inline OBJ * emList<OBJ>::GetWritable(const OBJ * elem)
671 {
672 	if (Data->RefCount>1) MakeWritable(&elem);
673 	return (OBJ*)elem;
674 }
675 
GetFirstWritable()676 template <class OBJ> inline OBJ * emList<OBJ>::GetFirstWritable()
677 {
678 	if (Data->RefCount>1) MakeWritable();
679 	return Data->First;
680 }
681 
GetLastWritable()682 template <class OBJ> inline OBJ * emList<OBJ>::GetLastWritable()
683 {
684 	if (Data->RefCount>1) MakeWritable();
685 	return Data->Last;
686 }
687 
GetNextWritable(const OBJ * elem)688 template <class OBJ> inline OBJ * emList<OBJ>::GetNextWritable(
689 	const OBJ * elem
690 )
691 {
692 	if (Data->RefCount>1) MakeWritable(&elem);
693 	return EM_LSTIMP_NEXT(elem);
694 }
695 
GetPrevWritable(const OBJ * elem)696 template <class OBJ> inline OBJ * emList<OBJ>::GetPrevWritable(
697 	const OBJ * elem
698 )
699 {
700 	if (Data->RefCount>1) MakeWritable(&elem);
701 	return EM_LSTIMP_NEXT(elem);
702 }
703 
Set(const OBJ * pos,const OBJ & obj)704 template <class OBJ> inline void emList<OBJ>::Set(
705 	const OBJ * pos, const OBJ & obj
706 )
707 {
708 	if (Data->RefCount>1) MakeWritable(&pos);
709 	*((OBJ*)pos)=obj;
710 }
711 
InsertAtBeg(const OBJ & obj)712 template <class OBJ> inline void emList<OBJ>::InsertAtBeg(const OBJ & obj)
713 {
714 	InsertAfter(NULL,obj);
715 }
716 
InsertAtBeg(const OBJ * elem)717 template <class OBJ> inline void emList<OBJ>::InsertAtBeg(const OBJ * elem)
718 {
719 	InsertAfter(NULL,*this,elem,elem);
720 }
721 
InsertAtBeg(const OBJ * first,const OBJ * last)722 template <class OBJ> inline void emList<OBJ>::InsertAtBeg(
723 	const OBJ * first, const OBJ * last
724 )
725 {
726 	InsertAfter(NULL,*this,first,last);
727 }
728 
InsertAtBeg(const emList & src)729 template <class OBJ> inline void emList<OBJ>::InsertAtBeg(
730 	const emList & src
731 )
732 {
733 	InsertAfter(NULL,src,src.Data->First,src.Data->Last);
734 }
735 
InsertAtBeg(const emList & src,const OBJ * elem)736 template <class OBJ> inline void emList<OBJ>::InsertAtBeg(
737 	const emList & src, const OBJ * elem
738 )
739 {
740 	InsertAfter(NULL,src,elem,elem);
741 }
742 
InsertAtBeg(const emList & src,const OBJ * first,const OBJ * last)743 template <class OBJ> inline void emList<OBJ>::InsertAtBeg(
744 	const emList & src, const OBJ * first, const OBJ * last
745 )
746 {
747 	InsertAfter(NULL,src,first,last);
748 }
749 
InsertAtEnd(const OBJ & obj)750 template <class OBJ> inline void emList<OBJ>::InsertAtEnd(const OBJ & obj)
751 {
752 	InsertBefore(NULL,obj);
753 }
754 
InsertAtEnd(const OBJ * elem)755 template <class OBJ> inline void emList<OBJ>::InsertAtEnd(const OBJ * elem)
756 {
757 	InsertBefore(NULL,*this,elem,elem);
758 }
759 
InsertAtEnd(const OBJ * first,const OBJ * last)760 template <class OBJ> inline void emList<OBJ>::InsertAtEnd(
761 	const OBJ * first, const OBJ * last
762 )
763 {
764 	InsertBefore(NULL,*this,first,last);
765 }
766 
InsertAtEnd(const emList & src)767 template <class OBJ> inline void emList<OBJ>::InsertAtEnd(const emList & src)
768 {
769 	InsertBefore(NULL,src,src.Data->First,src.Data->Last);
770 }
771 
InsertAtEnd(const emList & src,const OBJ * elem)772 template <class OBJ> inline void emList<OBJ>::InsertAtEnd(
773 	const emList & src, const OBJ * elem
774 )
775 {
776 	InsertBefore(NULL,src,elem,elem);
777 }
778 
InsertAtEnd(const emList & src,const OBJ * first,const OBJ * last)779 template <class OBJ> inline void emList<OBJ>::InsertAtEnd(
780 	const emList & src, const OBJ * first, const OBJ * last
781 )
782 {
783 	InsertBefore(NULL,src,first,last);
784 }
785 
InsertBefore(const OBJ * pos,const OBJ & obj)786 template <class OBJ> void emList<OBJ>::InsertBefore(
787 	const OBJ * pos, const OBJ & obj
788 )
789 {
790 	OBJ * e;
791 
792 	if (Data->RefCount>1 || Data->IsStaticEmpty) MakeWritable(&pos);
793 	e=&(new Element(obj))->Obj;
794 	if ((EM_LSTIMP_NEXT(e)=(OBJ*)pos)==NULL) {
795 		if ((EM_LSTIMP_PREV(e)=Data->Last)==NULL) Data->First=e;
796 		else EM_LSTIMP_NEXT(EM_LSTIMP_PREV(e))=e;
797 		Data->Last=e;
798 	}
799 	else {
800 		if ((EM_LSTIMP_PREV(e)=EM_LSTIMP_PREV(pos))==NULL) Data->First=e;
801 		else EM_LSTIMP_NEXT(EM_LSTIMP_PREV(e))=e;
802 		EM_LSTIMP_PREV(pos)=e;
803 	}
804 }
805 
InsertBefore(const OBJ * pos,const OBJ * elem)806 template <class OBJ> inline void emList<OBJ>::InsertBefore(
807 	const OBJ * pos, const OBJ * elem
808 )
809 {
810 	InsertBefore(pos,*this,elem,elem);
811 }
812 
InsertBefore(const OBJ * pos,const OBJ * first,const OBJ * last)813 template <class OBJ> inline void emList<OBJ>::InsertBefore(
814 	const OBJ * pos, const OBJ * first, const OBJ * last
815 )
816 {
817 	InsertBefore(pos,*this,first,last);
818 }
819 
InsertBefore(const OBJ * pos,const emList & src)820 template <class OBJ> inline void emList<OBJ>::InsertBefore(
821 	const OBJ * pos, const emList & src
822 )
823 {
824 	InsertBefore(pos,src,src.Data->First,src.Data->Last);
825 }
826 
InsertBefore(const OBJ * pos,const emList & src,const OBJ * elem)827 template <class OBJ> inline void emList<OBJ>::InsertBefore(
828 	const OBJ * pos, const emList & src, const OBJ * elem
829 )
830 {
831 	InsertBefore(pos,src,elem,elem);
832 }
833 
InsertBefore(const OBJ * pos,const emList & src,const OBJ * first,const OBJ * last)834 template <class OBJ> void emList<OBJ>::InsertBefore(
835 	const OBJ * pos, const emList & src, const OBJ * first,
836 	const OBJ * last
837 )
838 {
839 	OBJ * p, * e;
840 
841 	if (!first || !last) return;
842 	if (!Data->First && first==src.Data->First && last==src.Data->Last) {
843 		src.Data->RefCount++;
844 		if (!--Data->RefCount) DeleteData();
845 		Data=src.Data;
846 		return;
847 	}
848 	if (Data->RefCount>1 || Data->IsStaticEmpty) MakeWritable(&pos,&first,&last);
849 	p=(OBJ*)pos;
850 	for (;;) {
851 		e=&(new Element(*last))->Obj;
852 		if ((EM_LSTIMP_NEXT(e)=p)==NULL) {
853 			if ((EM_LSTIMP_PREV(e)=Data->Last)==NULL) Data->First=e;
854 			else EM_LSTIMP_NEXT(EM_LSTIMP_PREV(e))=e;
855 			Data->Last=e;
856 		}
857 		else {
858 			if ((EM_LSTIMP_PREV(e)=EM_LSTIMP_PREV(p))==NULL) Data->First=e;
859 			else EM_LSTIMP_NEXT(EM_LSTIMP_PREV(e))=e;
860 			EM_LSTIMP_PREV(p)=e;
861 		}
862 		if (last==first) break;
863 		p=e;
864 		if (last==pos) last=p;
865 		last=EM_LSTIMP_PREV(last);
866 	}
867 }
868 
InsertAfter(const OBJ * pos,const OBJ & obj)869 template <class OBJ> void emList<OBJ>::InsertAfter(
870 	const OBJ * pos, const OBJ & obj
871 )
872 {
873 	OBJ * e;
874 
875 	if (Data->RefCount>1 || Data->IsStaticEmpty) MakeWritable(&pos);
876 	e=&(new Element(obj))->Obj;
877 	if ((EM_LSTIMP_PREV(e)=(OBJ*)pos)==NULL) {
878 		if ((EM_LSTIMP_NEXT(e)=Data->First)==NULL) Data->Last=e;
879 		else EM_LSTIMP_PREV(EM_LSTIMP_NEXT(e))=e;
880 		Data->First=e;
881 	}
882 	else {
883 		if ((EM_LSTIMP_NEXT(e)=EM_LSTIMP_NEXT(pos))==NULL) Data->Last=e;
884 		else EM_LSTIMP_PREV(EM_LSTIMP_NEXT(e))=e;
885 		EM_LSTIMP_NEXT(pos)=e;
886 	}
887 }
888 
InsertAfter(const OBJ * pos,const OBJ * elem)889 template <class OBJ> inline void emList<OBJ>::InsertAfter(
890 	const OBJ * pos, const OBJ * elem
891 )
892 {
893 	InsertAfter(pos,*this,elem,elem);
894 }
895 
InsertAfter(const OBJ * pos,const OBJ * first,const OBJ * last)896 template <class OBJ> inline void emList<OBJ>::InsertAfter(
897 	const OBJ * pos, const OBJ * first, const OBJ * last
898 )
899 {
900 	InsertAfter(pos,*this,first,last);
901 }
902 
InsertAfter(const OBJ * pos,const emList & src)903 template <class OBJ> inline void emList<OBJ>::InsertAfter(
904 	const OBJ * pos, const emList & src
905 )
906 {
907 	InsertAfter(pos,src,src.Data->First,src.Data->Last);
908 }
909 
InsertAfter(const OBJ * pos,const emList & src,const OBJ * elem)910 template <class OBJ> inline void emList<OBJ>::InsertAfter(
911 	const OBJ * pos, const emList & src, const OBJ * elem
912 )
913 {
914 	InsertAfter(pos,src,elem,elem);
915 }
916 
InsertAfter(const OBJ * pos,const emList & src,const OBJ * first,const OBJ * last)917 template <class OBJ> void emList<OBJ>::InsertAfter(
918 	const OBJ * pos, const emList & src, const OBJ * first,
919 	const OBJ * last
920 )
921 {
922 	OBJ * p, * e;
923 
924 	if (!first || !last) return;
925 	if (!Data->First && first==src.Data->First && last==src.Data->Last) {
926 		src.Data->RefCount++;
927 		if (!--Data->RefCount) DeleteData();
928 		Data=src.Data;
929 		return;
930 	}
931 	if (Data->RefCount>1 || Data->IsStaticEmpty) MakeWritable(&pos,&first,&last);
932 	p=(OBJ*)pos;
933 	for (;;) {
934 		e=&(new Element(*first))->Obj;
935 		if ((EM_LSTIMP_PREV(e)=p)==NULL) {
936 			if ((EM_LSTIMP_NEXT(e)=Data->First)==NULL) Data->Last=e;
937 			else EM_LSTIMP_PREV(EM_LSTIMP_NEXT(e))=e;
938 			Data->First=e;
939 		}
940 		else {
941 			if ((EM_LSTIMP_NEXT(e)=EM_LSTIMP_NEXT(p))==NULL) Data->Last=e;
942 			else EM_LSTIMP_PREV(EM_LSTIMP_NEXT(e))=e;
943 			EM_LSTIMP_NEXT(p)=e;
944 		}
945 		if (first==last) break;
946 		p=e;
947 		if (first==pos) first=p;
948 		first=EM_LSTIMP_NEXT(first);
949 	}
950 }
951 
Add(const OBJ & obj)952 template <class OBJ> inline void emList<OBJ>::Add(const OBJ & obj)
953 {
954 	InsertBefore(NULL,obj);
955 }
956 
Add(const OBJ * elem)957 template <class OBJ> inline void emList<OBJ>::Add(const OBJ * elem)
958 {
959 	InsertBefore(NULL,*this,elem,elem);
960 }
961 
Add(const OBJ * first,const OBJ * last)962 template <class OBJ> inline void emList<OBJ>::Add(
963 	const OBJ * first, const OBJ * last
964 )
965 {
966 	InsertBefore(NULL,*this,first,last);
967 }
968 
Add(const emList & src)969 template <class OBJ> inline void emList<OBJ>::Add(const emList & src)
970 {
971 	InsertBefore(NULL,src,src.Data->First,src.Data->Last);
972 }
973 
Add(const emList & src,const OBJ * elem)974 template <class OBJ> inline void emList<OBJ>::Add(
975 	const emList & src, const OBJ * elem
976 )
977 {
978 	InsertBefore(NULL,src,elem,elem);
979 }
980 
Add(const emList & src,const OBJ * first,const OBJ * last)981 template <class OBJ> inline void emList<OBJ>::Add(
982 	const emList & src, const OBJ * first, const OBJ * last
983 )
984 {
985 	InsertBefore(NULL,src,first,last);
986 }
987 
988 template <class OBJ> inline emList<OBJ> & emList<OBJ>::operator += (
989 	const emList & list
990 )
991 {
992 	InsertBefore(NULL,list,list.Data->First,list.Data->Last);
993 	return *this;
994 }
995 
996 template <class OBJ> inline emList<OBJ> & emList<OBJ>::operator += (
997 	const OBJ & obj
998 )
999 {
1000 	InsertBefore(NULL,obj);
1001 	return *this;
1002 }
1003 
1004 template <class OBJ> inline emList<OBJ> emList<OBJ>::operator + (
1005 	const emList & list
1006 ) const
1007 {
1008 	return emList<OBJ>(*this,list);
1009 }
1010 
1011 template <class OBJ> inline emList<OBJ> emList<OBJ>::operator + (
1012 	const OBJ & obj
1013 ) const
1014 {
1015 	return emList<OBJ>(*this,obj);
1016 }
1017 
1018 template <class OBJ> inline emList<OBJ> operator + (
1019 	const OBJ & obj, const emList<OBJ> & list
1020 )
1021 {
1022 	return emList<OBJ>(obj,list);
1023 }
1024 
MoveToBeg(const OBJ * elem)1025 template <class OBJ> inline void emList<OBJ>::MoveToBeg(const OBJ * elem)
1026 {
1027 	MoveAfter(NULL,this,elem,elem);
1028 }
1029 
MoveToBeg(const OBJ * first,const OBJ * last)1030 template <class OBJ> inline void emList<OBJ>::MoveToBeg(
1031 	const OBJ * first, const OBJ * last
1032 )
1033 {
1034 	MoveAfter(NULL,this,first,last);
1035 }
1036 
MoveToBeg(emList * src)1037 template <class OBJ> inline void emList<OBJ>::MoveToBeg(emList * src)
1038 {
1039 	if (src) MoveAfter(NULL,src,src->Data->First,src->Data->Last);
1040 }
1041 
MoveToBeg(emList * src,const OBJ * elem)1042 template <class OBJ> inline void emList<OBJ>::MoveToBeg(
1043 	emList * src, const OBJ * elem
1044 )
1045 {
1046 	MoveAfter(NULL,src,elem,elem);
1047 }
1048 
MoveToBeg(emList * src,const OBJ * first,const OBJ * last)1049 template <class OBJ> inline void emList<OBJ>::MoveToBeg(
1050 	emList * src, const OBJ * first, const OBJ * last
1051 )
1052 {
1053 	MoveAfter(NULL,src,first,last);
1054 }
1055 
MoveToEnd(const OBJ * elem)1056 template <class OBJ> inline void emList<OBJ>::MoveToEnd(const OBJ * elem)
1057 {
1058 	MoveBefore(NULL,this,elem,elem);
1059 }
1060 
MoveToEnd(const OBJ * first,const OBJ * last)1061 template <class OBJ> inline void emList<OBJ>::MoveToEnd(
1062 	const OBJ * first, const OBJ * last
1063 )
1064 {
1065 	MoveBefore(NULL,this,first,last);
1066 }
1067 
MoveToEnd(emList * src)1068 template <class OBJ> inline void emList<OBJ>::MoveToEnd(emList * src)
1069 {
1070 	if (src) MoveBefore(NULL,src,src->Data->First,src->Data->Last);
1071 }
1072 
MoveToEnd(emList * src,const OBJ * elem)1073 template <class OBJ> inline void emList<OBJ>::MoveToEnd(
1074 	emList * src, const OBJ * elem
1075 )
1076 {
1077 	MoveBefore(NULL,src,elem,elem);
1078 }
1079 
MoveToEnd(emList * src,const OBJ * first,const OBJ * last)1080 template <class OBJ> inline void emList<OBJ>::MoveToEnd(
1081 	emList * src, const OBJ * first, const OBJ * last
1082 )
1083 {
1084 	MoveBefore(NULL,src,first,last);
1085 }
1086 
MoveBefore(const OBJ * pos,const OBJ * elem)1087 template <class OBJ> inline void emList<OBJ>::MoveBefore(
1088 	const OBJ * pos, const OBJ * elem
1089 )
1090 {
1091 	MoveBefore(pos,this,elem,elem);
1092 }
1093 
MoveBefore(const OBJ * pos,const OBJ * first,const OBJ * last)1094 template <class OBJ> inline void emList<OBJ>::MoveBefore(
1095 	const OBJ * pos, const OBJ * first, const OBJ * last
1096 )
1097 {
1098 	MoveBefore(pos,this,first,last);
1099 }
1100 
MoveBefore(const OBJ * pos,emList * src)1101 template <class OBJ> inline void emList<OBJ>::MoveBefore(
1102 	const OBJ * pos, emList * src
1103 )
1104 {
1105 	if (src) MoveBefore(pos,src,src->Data->First,src->Data->Last);
1106 }
1107 
MoveBefore(const OBJ * pos,emList * src,const OBJ * elem)1108 template <class OBJ> inline void emList<OBJ>::MoveBefore(
1109 	const OBJ * pos, emList * src, const OBJ * elem
1110 )
1111 {
1112 	MoveBefore(pos,src,elem,elem);
1113 }
1114 
MoveBefore(const OBJ * pos,emList * src,const OBJ * first,const OBJ * last)1115 template <class OBJ> void emList<OBJ>::MoveBefore(
1116 	const OBJ * pos, emList * src, const OBJ * first, const OBJ * last
1117 )
1118 {
1119 	Iterator * * pi;
1120 	Iterator * i;
1121 	const OBJ * e;
1122 
1123 	if (!first || !last) return;
1124 	if (!src) src=this;
1125 	if (src!=this) {
1126 		if (Data->RefCount>1 || Data->IsStaticEmpty) MakeWritable(&pos);
1127 		if (src->Data->RefCount>1) src->MakeWritable(&first,&last);
1128 		for (pi=&src->Iterators, i=*pi; i; i=*pi) {
1129 			if (i->Pos!=last) {
1130 				if (!i->Pos) { pi=&i->NextIter; continue; }
1131 				for (e=first; i->Pos!=e && e!=last; e=EM_LSTIMP_NEXT(e));
1132 				if (e==last) { pi=&i->NextIter; continue; }
1133 			}
1134 			*pi=i->NextIter;
1135 			i->List=this;
1136 			i->NextIter=Iterators;
1137 			Iterators=i;
1138 		}
1139 	}
1140 	else if (Data->RefCount>1) {
1141 		if (EM_LSTIMP_NEXT(last)==pos) return;
1142 		MakeWritable(&pos,&first,&last);
1143 	}
1144 	if (!EM_LSTIMP_PREV(first)) src->Data->First=EM_LSTIMP_NEXT(last);
1145 	else EM_LSTIMP_NEXT(EM_LSTIMP_PREV(first))=EM_LSTIMP_NEXT(last);
1146 	if (!EM_LSTIMP_NEXT(last)) src->Data->Last=EM_LSTIMP_PREV(first);
1147 	else EM_LSTIMP_PREV(EM_LSTIMP_NEXT(last))=EM_LSTIMP_PREV(first);
1148 	if ((EM_LSTIMP_NEXT(last)=(OBJ*)pos)==NULL) {
1149 		if ((EM_LSTIMP_PREV(first)=Data->Last)==NULL) Data->First=(OBJ*)first;
1150 		else EM_LSTIMP_NEXT(EM_LSTIMP_PREV(first))=(OBJ*)first;
1151 		Data->Last=(OBJ*)last;
1152 	}
1153 	else {
1154 		if ((EM_LSTIMP_PREV(first)=EM_LSTIMP_PREV(pos))==NULL) {
1155 			Data->First=(OBJ*)first;
1156 		}
1157 		else EM_LSTIMP_NEXT(EM_LSTIMP_PREV(first))=(OBJ*)first;
1158 		EM_LSTIMP_PREV(pos)=(OBJ*)last;
1159 	}
1160 }
1161 
MoveAfter(const OBJ * pos,const OBJ * elem)1162 template <class OBJ> inline void emList<OBJ>::MoveAfter(
1163 	const OBJ * pos, const OBJ * elem
1164 )
1165 {
1166 	MoveAfter(pos,this,elem,elem);
1167 }
1168 
MoveAfter(const OBJ * pos,const OBJ * first,const OBJ * last)1169 template <class OBJ> inline void emList<OBJ>::MoveAfter(
1170 	const OBJ * pos, const OBJ * first, const OBJ * last
1171 )
1172 {
1173 	MoveAfter(pos,this,first,last);
1174 }
1175 
MoveAfter(const OBJ * pos,emList * src)1176 template <class OBJ> inline void emList<OBJ>::MoveAfter(
1177 	const OBJ * pos, emList * src
1178 )
1179 {
1180 	if (src) MoveAfter(pos,src,src->Data->First,src->Data->Last);
1181 }
1182 
MoveAfter(const OBJ * pos,emList * src,const OBJ * elem)1183 template <class OBJ> inline void emList<OBJ>::MoveAfter(
1184 	const OBJ * pos, emList * src, const OBJ * elem
1185 )
1186 {
1187 	MoveAfter(pos,src,elem,elem);
1188 }
1189 
MoveAfter(const OBJ * pos,emList * src,const OBJ * first,const OBJ * last)1190 template <class OBJ> void emList<OBJ>::MoveAfter(
1191 	const OBJ * pos, emList * src, const OBJ * first, const OBJ * last
1192 )
1193 {
1194 	Iterator * * pi;
1195 	Iterator * i;
1196 	const OBJ * e;
1197 
1198 	if (!first || !last) return;
1199 	if (!src) src=this;
1200 	if (src!=this) {
1201 		if (Data->RefCount>1 || Data->IsStaticEmpty) MakeWritable(&pos);
1202 		if (src->Data->RefCount>1) src->MakeWritable(&first,&last);
1203 		for (pi=&src->Iterators, i=*pi; i; i=*pi) {
1204 			if (i->Pos!=last) {
1205 				if (!i->Pos) { pi=&i->NextIter; continue; }
1206 				for (e=first; i->Pos!=e && e!=last; e=EM_LSTIMP_NEXT(e));
1207 				if (e==last) { pi=&i->NextIter; continue; }
1208 			}
1209 			*pi=i->NextIter;
1210 			i->List=this;
1211 			i->NextIter=Iterators;
1212 			Iterators=i;
1213 		}
1214 	}
1215 	else if (Data->RefCount>1) {
1216 		if (EM_LSTIMP_PREV(first)==pos) return;
1217 		MakeWritable(&pos,&first,&last);
1218 	}
1219 	if (!EM_LSTIMP_PREV(first)) src->Data->First=EM_LSTIMP_NEXT(last);
1220 	else EM_LSTIMP_NEXT(EM_LSTIMP_PREV(first))=EM_LSTIMP_NEXT(last);
1221 	if (!EM_LSTIMP_NEXT(last)) src->Data->Last=EM_LSTIMP_PREV(first);
1222 	else EM_LSTIMP_PREV(EM_LSTIMP_NEXT(last))=EM_LSTIMP_PREV(first);
1223 	if ((EM_LSTIMP_PREV(first)=(OBJ*)pos)==NULL) {
1224 		if ((EM_LSTIMP_NEXT(last)=Data->First)==NULL) Data->Last=(OBJ*)last;
1225 		else EM_LSTIMP_PREV(EM_LSTIMP_NEXT(last))=(OBJ*)last;
1226 		Data->First=(OBJ*)first;
1227 	}
1228 	else {
1229 		if ((EM_LSTIMP_NEXT(last)=EM_LSTIMP_NEXT(pos))==NULL) {
1230 			Data->Last=(OBJ*)last;
1231 		}
1232 		else EM_LSTIMP_PREV(EM_LSTIMP_NEXT(last))=(OBJ*)last;
1233 		EM_LSTIMP_NEXT(pos)=(OBJ*)first;
1234 	}
1235 }
1236 
GetSubListOfFirst()1237 template <class OBJ> inline emList<OBJ> emList<OBJ>::GetSubListOfFirst() const
1238 {
1239 	return emList<OBJ>(*this,Data->First,Data->First);
1240 }
1241 
GetSubListOfLast()1242 template <class OBJ> inline emList<OBJ> emList<OBJ>::GetSubListOfLast() const
1243 {
1244 	return emList<OBJ>(*this,Data->Last,Data->Last);
1245 }
1246 
GetSubList(const OBJ * elem)1247 template <class OBJ> inline emList<OBJ> emList<OBJ>::GetSubList(
1248 	const OBJ * elem
1249 ) const
1250 {
1251 	return emList<OBJ>(*this,elem,elem);
1252 }
1253 
GetSubList(const OBJ * first,const OBJ * last)1254 template <class OBJ> inline emList<OBJ> emList<OBJ>::GetSubList(
1255 	const OBJ * first, const OBJ * last
1256 ) const
1257 {
1258 	return emList<OBJ>(*this,first,last);
1259 }
1260 
ExtractFirst()1261 template <class OBJ> inline emList<OBJ> emList<OBJ>::ExtractFirst()
1262 {
1263 	return Extract(Data->First,Data->First);
1264 }
1265 
ExtractLast()1266 template <class OBJ> inline emList<OBJ> emList<OBJ>::ExtractLast()
1267 {
1268 	return Extract(Data->Last,Data->Last);
1269 }
1270 
Extract(const OBJ * elem)1271 template <class OBJ> inline emList<OBJ> emList<OBJ>::Extract(const OBJ * elem)
1272 {
1273 	return Extract(elem,elem);
1274 }
1275 
Extract(const OBJ * first,const OBJ * last)1276 template <class OBJ> emList<OBJ> emList<OBJ>::Extract(
1277 	const OBJ * first, const OBJ * last
1278 )
1279 {
1280 	SharedData * d;
1281 	const OBJ * e;
1282 	Iterator * i;
1283 
1284 	if (!first || !last) {
1285 		d=&EmptyData;
1286 	}
1287 	else if (first==Data->First && last==Data->Last) {
1288 		for (i=Iterators; i; i=i->NextIter) i->Pos=NULL;
1289 		d=Data;
1290 		Data=&EmptyData;
1291 	}
1292 	else {
1293 		if (Data->RefCount>1) MakeWritable(&first,&last);
1294 		for (i=Iterators; i; i=i->NextIter) {
1295 			if (i->Pos!=last) {
1296 				if (!i->Pos) continue;
1297 				for (e=first; i->Pos!=e && e!=last; e=EM_LSTIMP_NEXT(e));
1298 				if (e==last) continue;
1299 			}
1300 			i->Pos=EM_LSTIMP_NEXT(last);
1301 		}
1302 		if (!EM_LSTIMP_PREV(first)) {
1303 			Data->First=EM_LSTIMP_NEXT(last);
1304 		}
1305 		else {
1306 			EM_LSTIMP_NEXT(EM_LSTIMP_PREV(first))=EM_LSTIMP_NEXT(last);
1307 			EM_LSTIMP_PREV(first)=NULL;
1308 		}
1309 		if (!EM_LSTIMP_NEXT(last)) {
1310 			Data->Last=EM_LSTIMP_PREV(first);
1311 		}
1312 		else {
1313 			EM_LSTIMP_PREV(EM_LSTIMP_NEXT(last))=EM_LSTIMP_PREV(first);
1314 			EM_LSTIMP_NEXT(last)=NULL;
1315 		}
1316 		d=new SharedData;
1317 		d->First=(OBJ*)first;
1318 		d->Last=(OBJ*)last;
1319 		d->IsStaticEmpty=false;
1320 		d->RefCount=1;
1321 	}
1322 	return emList<OBJ>(d);
1323 }
1324 
RemoveFirst()1325 template <class OBJ> inline void emList<OBJ>::RemoveFirst()
1326 {
1327 	Remove(Data->First,Data->First);
1328 }
1329 
RemoveLast()1330 template <class OBJ> inline void emList<OBJ>::RemoveLast()
1331 {
1332 	Remove(Data->Last,Data->Last);
1333 }
1334 
Remove(const OBJ * elem)1335 template <class OBJ> inline void emList<OBJ>::Remove(const OBJ * elem)
1336 {
1337 	Remove(elem,elem);
1338 }
1339 
Remove(const OBJ * first,const OBJ * last)1340 template <class OBJ> void emList<OBJ>::Remove(
1341 	const OBJ * first, const OBJ * last
1342 )
1343 {
1344 	const OBJ * e;
1345 	OBJ * e2;
1346 	Iterator * i;
1347 	SharedData * d;
1348 
1349 	if (!first || !last) return;
1350 	if (first==Data->First && last==Data->Last) {
1351 		for (i=Iterators; i; i=i->NextIter) i->Pos=NULL;
1352 		if (Data->RefCount>1) {
1353 			Data->RefCount--;
1354 			Data=&EmptyData;
1355 			return;
1356 		}
1357 	}
1358 	else {
1359 		for (i=Iterators; i; i=i->NextIter) {
1360 			if (i->Pos!=last) {
1361 				if (!i->Pos) continue;
1362 				for (e=first; i->Pos!=e && e!=last; e=EM_LSTIMP_NEXT(e));
1363 				if (e==last) continue;
1364 			}
1365 			i->Pos=EM_LSTIMP_NEXT(last);
1366 		}
1367 	}
1368 	if (Data->RefCount==1) {
1369 		if (!EM_LSTIMP_PREV(first)) Data->First=EM_LSTIMP_NEXT(last);
1370 		else EM_LSTIMP_NEXT(EM_LSTIMP_PREV(first))=EM_LSTIMP_NEXT(last);
1371 		if (!EM_LSTIMP_NEXT(last)) Data->Last=EM_LSTIMP_PREV(first);
1372 		else EM_LSTIMP_PREV(EM_LSTIMP_NEXT(last))=EM_LSTIMP_PREV(first);
1373 		do {
1374 			e=first;
1375 			first=EM_LSTIMP_NEXT(first);
1376 			delete EM_LSTIMP_ELEM(e);
1377 		} while (e!=last);
1378 	}
1379 	else {
1380 		d=new SharedData;
1381 		d->First=NULL;
1382 		d->Last=NULL;
1383 		d->IsStaticEmpty=false;
1384 		d->RefCount=1;
1385 		for (e=Data->First; e; e=EM_LSTIMP_NEXT(e)) {
1386 			if (e==first) {
1387 				e=EM_LSTIMP_NEXT(last);
1388 				if (!e) break;
1389 			}
1390 			e2=&(new Element(*e))->Obj;
1391 			EM_LSTIMP_NEXT(e2)=NULL;
1392 			if ((EM_LSTIMP_PREV(e2)=d->Last)==NULL) d->First=e2;
1393 			else EM_LSTIMP_NEXT(EM_LSTIMP_PREV(e2))=e2;
1394 			d->Last=e2;
1395 			for (i=Iterators; i; i=i->NextIter) {
1396 				if (i->Pos==e) i->Pos=e2;
1397 			}
1398 		}
1399 		Data->RefCount--;
1400 		Data=d;
1401 	}
1402 }
1403 
Clear(bool compact)1404 template <class OBJ> void emList<OBJ>::Clear(bool compact)
1405 {
1406 	OBJ * e1, * e2;
1407 	Iterator * i;
1408 
1409 	for (i=Iterators; i; i=i->NextIter) i->Pos=NULL;
1410 	if (Data->RefCount>1 || compact) {
1411 		if (!--Data->RefCount) DeleteData();
1412 		Data=&EmptyData;
1413 	}
1414 	else {
1415 		for (e1=Data->First; e1; e1=e2) {
1416 			e2=EM_LSTIMP_NEXT(e1);
1417 			delete EM_LSTIMP_ELEM(e1);
1418 		}
1419 		Data->First=NULL;
1420 		Data->Last=NULL;
1421 	}
1422 }
1423 
IsEmpty()1424 template <class OBJ> inline bool emList<OBJ>::IsEmpty() const
1425 {
1426 	return !Data->First;
1427 }
1428 
Sort(int (* compare)(const OBJ * obj1,const OBJ * obj2,void * context),void * context)1429 template <class OBJ> bool emList<OBJ>::Sort(
1430 	int(*compare)(const OBJ * obj1, const OBJ * obj2, void * context),
1431 	void * context
1432 )
1433 {
1434 	if (Data->First==Data->Last) return false;
1435 	if (Data->RefCount>1) MakeWritable();
1436 	return emSortDoubleLinkedList(
1437 		(void**)(void*)&Data->First,
1438 		(void**)(void*)&Data->Last,
1439 		offsetof(Element,Next)-offsetof(Element,Obj),
1440 		offsetof(Element,Prev)-offsetof(Element,Obj),
1441 		(int(*)(void*,void*,void*))compare,
1442 		context
1443 	);
1444 }
1445 
GetCount()1446 template <class OBJ> int emList<OBJ>::GetCount() const
1447 {
1448 	const OBJ * e;
1449 	int cnt;
1450 
1451 	for (cnt=0, e=Data->First; e; cnt++, e=EM_LSTIMP_NEXT(e));
1452 	return cnt;
1453 }
1454 
GetAtIndex(int index)1455 template <class OBJ> const OBJ * emList<OBJ>::GetAtIndex(int index) const
1456 {
1457 	const OBJ * e;
1458 
1459 	if (index<0) e=NULL;
1460 	else for (e=Data->First; e && --index>=0; e=EM_LSTIMP_NEXT(e));
1461 	return e;
1462 }
1463 
GetIndexOf(const OBJ * elem)1464 template <class OBJ> int emList<OBJ>::GetIndexOf(const OBJ * elem) const
1465 {
1466 	const OBJ * e;
1467 	int i;
1468 
1469 	for (i=0, e=Data->First; e; i++, e=EM_LSTIMP_NEXT(e)) {
1470 		if (e==elem) return i;
1471 	}
1472 	return -1;
1473 }
1474 
GetDataRefCount()1475 template <class OBJ> unsigned int emList<OBJ>::GetDataRefCount() const
1476 {
1477 	return Data->IsStaticEmpty ? UINT_MAX/2 : Data->RefCount;
1478 }
1479 
MakeNonShared()1480 template <class OBJ> inline void emList<OBJ>::MakeNonShared()
1481 {
1482 	MakeWritable();
1483 }
1484 
Iterator()1485 template <class OBJ> inline emList<OBJ>::Iterator::Iterator()
1486 {
1487 	Pos=NULL;
1488 	List=NULL;
1489 }
1490 
Iterator(const typename emList<OBJ>::Iterator & iter)1491 template <class OBJ> emList<OBJ>::Iterator::Iterator(
1492 	const typename emList<OBJ>::Iterator & iter
1493 )
1494 {
1495 	Pos=iter.Pos;
1496 	if ((List=iter.List)!=NULL) {
1497 		NextIter=List->Iterators;
1498 		List->Iterators=this;
1499 	}
1500 }
1501 
Iterator(const emList<OBJ> & list,const OBJ * elem)1502 template <class OBJ> emList<OBJ>::Iterator::Iterator(
1503 	const emList<OBJ> & list, const OBJ * elem
1504 )
1505 {
1506 	Pos=elem;
1507 	if ((List=(emList<OBJ>*)&list)!=NULL) {
1508 		NextIter=List->Iterators;
1509 		List->Iterators=this;
1510 	}
1511 }
1512 
~Iterator()1513 template <class OBJ> emList<OBJ>::Iterator::~Iterator()
1514 {
1515 	Iterator * * pi;
1516 
1517 	if (List) {
1518 		for (pi=&List->Iterators; *pi!=this; pi=&(*pi)->NextIter);
1519 		*pi=NextIter;
1520 	}
1521 }
1522 
1523 template <class OBJ> inline typename emList<OBJ>::Iterator &
1524 	emList<OBJ>::Iterator::operator = (const Iterator & iter)
1525 {
1526 	Set(iter);
1527 	return *this;
1528 }
1529 
1530 template <class OBJ> inline
1531 	emList<OBJ>::Iterator::operator const OBJ * () const
1532 {
1533 	return Pos;
1534 }
1535 
1536 template <class OBJ> inline
1537 	const OBJ * emList<OBJ>::Iterator::operator * () const
1538 {
1539 	return Pos;
1540 }
1541 
1542 template <class OBJ> inline
1543 	const OBJ * emList<OBJ>::Iterator::operator -> () const
1544 {
1545 	return Pos;
1546 }
1547 
Get()1548 template <class OBJ> inline const OBJ * emList<OBJ>::Iterator::Get() const
1549 {
1550 	return Pos;
1551 }
1552 
Set(const Iterator & iter)1553 template <class OBJ> const OBJ * emList<OBJ>::Iterator::Set(
1554 	const Iterator & iter
1555 )
1556 {
1557 	Iterator * * pi;
1558 
1559 	if (List!=iter.List) {
1560 		if (List) {
1561 			for (pi=&List->Iterators; *pi!=this; pi=&(*pi)->NextIter);
1562 			*pi=NextIter;
1563 		}
1564 		if ((List=iter.List)!=NULL) {
1565 			NextIter=List->Iterators;
1566 			List->Iterators=this;
1567 		}
1568 	}
1569 	Pos=iter.Pos;
1570 	return Pos;
1571 }
1572 
Set(const emList<OBJ> & list,const OBJ * elem)1573 template <class OBJ> const OBJ * emList<OBJ>::Iterator::Set(
1574 	const emList<OBJ> & list, const OBJ * elem
1575 )
1576 {
1577 	Iterator * * pi;
1578 
1579 	if (List!=&list) {
1580 		if (List) {
1581 			for (pi=&List->Iterators; *pi!=this; pi=&(*pi)->NextIter);
1582 			*pi=NextIter;
1583 		}
1584 		List=(emList<OBJ>*)&list;
1585 		NextIter=List->Iterators;
1586 		List->Iterators=this;
1587 	}
1588 	Pos=elem;
1589 	return elem;
1590 }
1591 
SetFirst(const emList<OBJ> & list)1592 template <class OBJ> inline const OBJ * emList<OBJ>::Iterator::SetFirst(
1593 	const emList<OBJ> & list
1594 )
1595 {
1596 	return Set(list,list.Data->First);
1597 }
1598 
SetLast(const emList<OBJ> & list)1599 template <class OBJ> inline const OBJ * emList<OBJ>::Iterator::SetLast(
1600 	const emList<OBJ> & list
1601 )
1602 {
1603 	return Set(list,list.Data->Last);
1604 }
1605 
SetNext()1606 template <class OBJ> inline const OBJ * emList<OBJ>::Iterator::SetNext()
1607 {
1608 	Pos=EM_LSTIMP_NEXT(Pos);
1609 	return Pos;
1610 }
1611 
SetPrev()1612 template <class OBJ> inline const OBJ * emList<OBJ>::Iterator::SetPrev()
1613 {
1614 	Pos=EM_LSTIMP_PREV(Pos);
1615 	return Pos;
1616 }
1617 
1618 template <class OBJ> inline const OBJ * emList<OBJ>::Iterator::operator ++()
1619 {
1620 	Pos=EM_LSTIMP_NEXT(Pos);
1621 	return Pos;
1622 }
1623 
1624 template <class OBJ> inline const OBJ * emList<OBJ>::Iterator::operator --()
1625 {
1626 	Pos=EM_LSTIMP_PREV(Pos);
1627 	return Pos;
1628 }
1629 
1630 template <class OBJ> inline const OBJ * emList<OBJ>::Iterator::operator ++(int)
1631 {
1632 	const OBJ * res=Pos;
1633 	Pos=EM_LSTIMP_NEXT(Pos);
1634 	return res;
1635 }
1636 
1637 template <class OBJ> inline const OBJ * emList<OBJ>::Iterator::operator --(int)
1638 {
1639 	const OBJ * res=Pos;
1640 	Pos=EM_LSTIMP_PREV(Pos);
1641 	return res;
1642 }
1643 
1644 template <class OBJ> inline bool emList<OBJ>::Iterator::operator == (
1645 	const Iterator & iter
1646 ) const
1647 {
1648 	return Pos==iter.Pos;
1649 }
1650 
1651 template <class OBJ> inline bool emList<OBJ>::Iterator::operator != (
1652 	const Iterator & iter
1653 ) const
1654 {
1655 	return Pos!=iter.Pos;
1656 }
1657 
1658 template <class OBJ> inline bool emList<OBJ>::Iterator::operator == (
1659 	const OBJ * elem
1660 ) const
1661 {
1662 	return Pos==elem;
1663 }
1664 
1665 template <class OBJ> inline bool emList<OBJ>::Iterator::operator != (
1666 	const OBJ * elem
1667 ) const
1668 {
1669 	return Pos!=elem;
1670 }
1671 
1672 template <class OBJ> inline
GetList()1673 	const emList<OBJ> * emList<OBJ>::Iterator::GetList() const
1674 {
1675 	return List;
1676 }
1677 
Detach()1678 template <class OBJ> void emList<OBJ>::Iterator::Detach()
1679 {
1680 	Iterator * * pi;
1681 
1682 	if (List) {
1683 		for (pi=&List->Iterators; *pi!=this; pi=&(*pi)->NextIter);
1684 		*pi=NextIter;
1685 		List=NULL;
1686 		Pos=NULL;
1687 	}
1688 }
1689 
1690 template <class OBJ> typename emList<OBJ>::SharedData emList<OBJ>::EmptyData=
1691 {
1692 	NULL,NULL,true,UINT_MAX/2
1693 };
1694 
MakeWritable()1695 template <class OBJ> void emList<OBJ>::MakeWritable()
1696 {
1697 	const OBJ * p1, * p2, * p3;
1698 
1699 	p1=NULL; p2=NULL; p3=NULL;
1700 	MakeWritable(&p1,&p2,&p3);
1701 }
1702 
MakeWritable(const OBJ ** preserve)1703 template <class OBJ> void emList<OBJ>::MakeWritable(const OBJ * * preserve)
1704 {
1705 	const OBJ * p2, * p3;
1706 
1707 	p2=NULL; p3=NULL;
1708 	MakeWritable(preserve,&p2,&p3);
1709 }
1710 
MakeWritable(const OBJ ** preserve1,const OBJ ** preserve2)1711 template <class OBJ> void emList<OBJ>::MakeWritable(
1712 	const OBJ * * preserve1, const OBJ * * preserve2
1713 )
1714 {
1715 	const OBJ * p3;
1716 
1717 	p3=NULL;
1718 	MakeWritable(preserve1,preserve2,&p3);
1719 }
1720 
MakeWritable(const OBJ ** preserve1,const OBJ ** preserve2,const OBJ ** preserve3)1721 template <class OBJ> void emList<OBJ>::MakeWritable(
1722 	const OBJ * * preserve1, const OBJ * * preserve2,
1723 	const OBJ * * preserve3
1724 )
1725 {
1726 	SharedData * d1, * d2;
1727 	OBJ * e1, * e2;
1728 	Iterator * i;
1729 
1730 	d1=Data;
1731 	if (d1->RefCount>1 || Data->IsStaticEmpty) {
1732 		d2=new SharedData;
1733 		d2->First=NULL;
1734 		d2->Last=NULL;
1735 		d2->IsStaticEmpty=false;
1736 		d2->RefCount=1;
1737 		d1->RefCount--;
1738 		Data=d2;
1739 		for (e1=d1->First; e1; e1=EM_LSTIMP_NEXT(e1)) {
1740 			e2=&(new Element(*e1))->Obj;
1741 			EM_LSTIMP_NEXT(e2)=NULL;
1742 			if ((EM_LSTIMP_PREV(e2)=d2->Last)==NULL) d2->First=e2;
1743 			else EM_LSTIMP_NEXT(EM_LSTIMP_PREV(e2))=e2;
1744 			d2->Last=e2;
1745 			for (i=Iterators; i; i=i->NextIter) {
1746 				if (i->Pos==e1) i->Pos=e2;
1747 			}
1748 			if (*preserve1==e1) *preserve1=e2;
1749 			if (*preserve2==e1) *preserve2=e2;
1750 			if (*preserve3==e1) *preserve3=e2;
1751 		}
1752 	}
1753 }
1754 
DeleteData()1755 template <class OBJ> void emList<OBJ>::DeleteData()
1756 {
1757 	OBJ * e, * n;
1758 
1759 	EmptyData.RefCount=UINT_MAX/2;
1760 
1761 	// Never do a
1762 	//  if (Data!=&EmptyData)...
1763 	// instead of
1764 	//  if (!Data->IsStaticEmpty)...
1765 	// because static member variables of template classes could exist
1766 	// multiple times for the same final type (e.g. with Windows DLLs).
1767 	if (!Data->IsStaticEmpty) {
1768 		for (e=Data->First; e; e=n) {
1769 			n=EM_LSTIMP_NEXT(e);
1770 			delete EM_LSTIMP_ELEM(e);
1771 		}
1772 		delete Data;
1773 	}
1774 }
1775 
1776 
1777 #endif
1778