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