ROOT  6.06/09
Reference Guide
TList.cxx
Go to the documentation of this file.
1 // @(#)root/cont:$Id$
2 // Author: Fons Rademakers 10/08/95
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /** \class TList
13 A doubly linked list.
14 
15 All classes inheriting from TObject can be
16 inserted in a TList. Before being inserted into the list the object
17 pointer is wrapped in a TObjLink object which contains, besides
18 the object pointer also a previous and next pointer.
19 
20 There are basically four ways to iterate over a TList (in order
21 of preference, if not forced by other constraints):
22 
23  1. Using the R__FOR_EACH macro:
24 ~~~ {.cpp}
25  GetListOfPrimitives()->R__FOR_EACH(TObject,Paint)(option);
26 ~~~
27  2. Using the TList iterator TListIter (via the wrapper class TIter):
28 ~~~ {.cpp}
29  TIter next(GetListOfPrimitives());
30  while ((TObject *obj = next()))
31  obj->Draw(next.GetOption());
32 ~~~
33  3. Using the TList iterator TListIter and std::for_each algorithm:
34 ~~~ {.cpp}
35  // A function object, which will be applied to each element
36  // of the given range.
37  struct STestFunctor {
38  bool operator()(TObject *aObj) {
39  ...
40  return true;
41  }
42  }
43  ...
44  ...
45  TIter iter(mylist);
46  for_each( iter.Begin(), TIter::End(), STestFunctor() );
47 ~~~
48  4. Using the TObjLink list entries (that wrap the TObject*):
49 ~~~ {.cpp}
50  TObjLink *lnk = GetListOfPrimitives()->FirstLink();
51  while (lnk) {
52  lnk->GetObject()->Draw(lnk->GetOption());
53  lnk = lnk->Next();
54  }
55 ~~~
56  5. Using the TList's After() and Before() member functions:
57 ~~~ {.cpp}
58  TFree *idcur = this;
59  while (idcur) {
60  ...
61  ...
62  idcur = (TFree*)GetListOfFree()->After(idcur);
63  }
64 ~~~
65 Methods 2, 3 and 4 can also easily iterate backwards using either
66 a backward TIter (using argument kIterBackward) or by using
67 LastLink() and lnk->Prev() or by using the Before() member.
68 */
69 
70 #include "TList.h"
71 #include "TClass.h"
72 #include "TROOT.h"
73 #include "TVirtualMutex.h"
74 
75 #include <string>
76 namespace std {} using namespace std;
77 
79 
80 ////////////////////////////////////////////////////////////////////////////////
81 /// Delete the list. Objects are not deleted unless the TList is the
82 /// owner (set via SetOwner()).
83 
84 TList::~TList()
85 {
86  Clear();
87 }
88 
89 ////////////////////////////////////////////////////////////////////////////////
90 /// Add object at the beginning of the list.
91 
93 {
94  if (IsArgNull("AddFirst", obj)) return;
95 
96  if (!fFirst) {
97  fFirst = NewLink(obj);
98  fLast = fFirst;
99  } else {
100  TObjLink *t = NewLink(obj);
101  t->fNext = fFirst;
102  fFirst->fPrev = t;
103  fFirst = t;
104  }
105  fSize++;
106  Changed();
107 }
108 
109 ////////////////////////////////////////////////////////////////////////////////
110 /// Add object at the beginning of the list and also store option.
111 /// Storing an option is useful when one wants to change the behaviour
112 /// of an object a little without having to create a complete new
113 /// copy of the object. This feature is used, for example, by the Draw()
114 /// method. It allows the same object to be drawn in different ways.
115 
117 {
118  if (IsArgNull("AddFirst", obj)) return;
119 
120  if (!fFirst) {
121  fFirst = NewOptLink(obj, opt);
122  fLast = fFirst;
123  } else {
124  TObjLink *t = NewOptLink(obj, opt);
125  t->fNext = fFirst;
126  fFirst->fPrev = t;
127  fFirst = t;
128  }
129  fSize++;
130  Changed();
131 }
132 
133 ////////////////////////////////////////////////////////////////////////////////
134 /// Add object at the end of the list.
135 
137 {
138  if (IsArgNull("AddLast", obj)) return;
139 
140  if (!fFirst) {
141  fFirst = NewLink(obj);
142  fLast = fFirst;
143  } else
144  fLast = NewLink(obj, fLast);
145  fSize++;
146  Changed();
147 }
148 
149 ////////////////////////////////////////////////////////////////////////////////
150 /// Add object at the end of the list and also store option.
151 /// Storing an option is useful when one wants to change the behaviour
152 /// of an object a little without having to create a complete new
153 /// copy of the object. This feature is used, for example, by the Draw()
154 /// method. It allows the same object to be drawn in different ways.
155 
157 {
158  if (IsArgNull("AddLast", obj)) return;
159 
160  if (!fFirst) {
161  fFirst = NewOptLink(obj, opt);
162  fLast = fFirst;
163  } else
164  fLast = NewOptLink(obj, opt, fLast);
165  fSize++;
166  Changed();
167 }
168 
169 ////////////////////////////////////////////////////////////////////////////////
170 /// Insert object before object before in the list.
171 
172 void TList::AddBefore(const TObject *before, TObject *obj)
173 {
174  if (IsArgNull("AddBefore", obj)) return;
175 
176  if (!before)
177  TList::AddFirst(obj);
178  else {
179  Int_t idx;
180  TObjLink *t = FindLink(before, idx);
181  if (!t) {
182  Error("AddBefore", "before not found, object not added");
183  return;
184  }
185  if (t == fFirst)
186  TList::AddFirst(obj);
187  else {
188  NewLink(obj, t->Prev());
189  fSize++;
190  Changed();
191  }
192  }
193 }
194 
195 ////////////////////////////////////////////////////////////////////////////////
196 /// Insert object before the specified ObjLink object. If before = 0 then add
197 /// to the head of the list. An ObjLink can be obtained by looping over a list
198 /// using the above describe iterator method 3.
199 
200 void TList::AddBefore(TObjLink *before, TObject *obj)
201 {
202  if (IsArgNull("AddBefore", obj)) return;
203 
204  if (!before)
205  TList::AddFirst(obj);
206  else {
207  if (before == fFirst)
208  TList::AddFirst(obj);
209  else {
210  NewLink(obj, before->Prev());
211  fSize++;
212  Changed();
213  }
214  }
215 }
216 
217 ////////////////////////////////////////////////////////////////////////////////
218 /// Insert object after object after in the list.
219 
220 void TList::AddAfter(const TObject *after, TObject *obj)
221 {
222  if (IsArgNull("AddAfter", obj)) return;
223 
224  if (!after)
225  TList::AddLast(obj);
226  else {
227  Int_t idx;
228  TObjLink *t = FindLink(after, idx);
229  if (!t) {
230  Error("AddAfter", "after not found, object not added");
231  return;
232  }
233  if (t == fLast)
234  TList::AddLast(obj);
235  else {
236  NewLink(obj, t);
237  fSize++;
238  Changed();
239  }
240  }
241 }
242 
243 ////////////////////////////////////////////////////////////////////////////////
244 /// Insert object after the specified ObjLink object. If after = 0 then add
245 /// to the tail of the list. An ObjLink can be obtained by looping over a list
246 /// using the above describe iterator method 3.
247 
248 void TList::AddAfter(TObjLink *after, TObject *obj)
249 {
250  if (IsArgNull("AddAfter", obj)) return;
251 
252  if (!after)
253  TList::AddLast(obj);
254  else {
255  if (after == fLast)
256  TList::AddLast(obj);
257  else {
258  NewLink(obj, after);
259  fSize++;
260  Changed();
261  }
262  }
263 }
264 
265 ////////////////////////////////////////////////////////////////////////////////
266 /// Insert object at position idx in the list.
267 
268 void TList::AddAt(TObject *obj, Int_t idx)
269 {
270  if (IsArgNull("AddAt", obj)) return;
271 
272  TObjLink *lnk = LinkAt(idx);
273  if (!lnk)
274  TList::AddLast(obj);
275  else if (lnk == fFirst)
276  TList::AddFirst(obj);
277  else {
278  NewLink(obj, lnk->Prev());
279  fSize++;
280  Changed();
281  }
282 }
283 
284 ////////////////////////////////////////////////////////////////////////////////
285 /// Returns the object after object obj. Obj is found using the
286 /// object's IsEqual() method. Returns 0 if obj is last in list.
287 
288 TObject *TList::After(const TObject *obj) const
289 {
290  TObjLink *t;
291 
292  if (fCache && fCache->GetObject() && fCache->GetObject()->IsEqual(obj)) {
293  t = fCache;
294  ((TList*)this)->fCache = fCache->Next(); //cast const away, fCache should be mutable
295  } else {
296  Int_t idx;
297  t = FindLink(obj, idx);
298  if (t) ((TList*)this)->fCache = t->Next();
299  }
300 
301  if (t && t->Next())
302  return t->Next()->GetObject();
303  else
304  return 0;
305 }
306 
307 ////////////////////////////////////////////////////////////////////////////////
308 /// Returns the object at position idx. Returns 0 if idx is out of range.
309 
311 {
312  TObjLink *lnk = LinkAt(idx);
313  if (lnk) return lnk->GetObject();
314  return 0;
315 }
316 
317 ////////////////////////////////////////////////////////////////////////////////
318 /// Returns the object before object obj. Obj is found using the
319 /// object's IsEqual() method. Returns 0 if obj is first in list.
320 
321 TObject *TList::Before(const TObject *obj) const
322 {
323  TObjLink *t;
324 
325  if (fCache && fCache->GetObject() && fCache->GetObject()->IsEqual(obj)) {
326  t = fCache;
327  ((TList*)this)->fCache = fCache->Prev(); //cast const away, fCache should be mutable
328  } else {
329  Int_t idx;
330  t = FindLink(obj, idx);
331  if (t) ((TList*)this)->fCache = t->Prev();
332  }
333 
334  if (t && t->Prev())
335  return t->Prev()->GetObject();
336  else
337  return 0;
338 }
339 
340 ////////////////////////////////////////////////////////////////////////////////
341 /// Remove all objects from the list. Does not delete the objects
342 /// unless the TList is the owner (set via SetOwner()) and option
343 /// "nodelete" is not set.
344 /// If option="nodelete" then don't delete any heap objects that were
345 /// marked with the kCanDelete bit, otherwise these objects will be
346 /// deleted (this option is used by THashTable::Clear()).
347 
348 void TList::Clear(Option_t *option)
349 {
350  Bool_t nodel = option ? (!strcmp(option, "nodelete") ? kTRUE : kFALSE) : kFALSE;
351 
352  if (!nodel && IsOwner()) {
353  Delete(option);
354  return;
355  }
356 
357  // In some case, for example TParallelCoord, a list (the pad's list of
358  // primitives) will contain both the container and the containees
359  // (the TParallelCoorVar) but if the Clear is being called from
360  // the destructor of the container of this list, one of the first
361  // thing done will be the remove the container (the pad) for the
362  // list (of Primitives of the canvas) that was connecting it
363  // (indirectly) to the list of cleanups.
364  // So let's temporarily add the current list and remove it later.
365  bool needRegister = fFirst && TROOT::Initialized();
366  if(needRegister) {
368  needRegister = needRegister && !gROOT->GetListOfCleanups()->FindObject(this);
369  }
370  if (needRegister) {
372  gROOT->GetListOfCleanups()->Add(this);
373  }
374  while (fFirst) {
375  TObjLink *tlk = fFirst;
376  fFirst = fFirst->Next();
377  fSize--;
378  // delete only heap objects marked OK to clear
379  if (!nodel && tlk->GetObject() && tlk->GetObject()->IsOnHeap()) {
380  if (tlk->GetObject()->TestBit(kCanDelete)) {
381  if(tlk->GetObject()->TestBit(kNotDeleted)) {
383  }
384  }
385  }
386  delete tlk;
387  }
388  if (needRegister) {
391  }
392  fFirst = fLast = fCache = 0;
393  fSize = 0;
394  Changed();
395 }
396 
397 ////////////////////////////////////////////////////////////////////////////////
398 /// Remove all objects from the list AND delete all heap based objects.
399 /// If option="slow" then keep list consistent during delete. This allows
400 /// recursive list operations during the delete (e.g. during the dtor
401 /// of an object in this list one can still access the list to search for
402 /// other not yet deleted objects).
403 
404 void TList::Delete(Option_t *option)
405 {
406  Bool_t slow = option ? (!strcmp(option, "slow") ? kTRUE : kFALSE) : kFALSE;
407 
408  TList removeDirectory; // need to deregister these from their directory
409 
410  if (slow) {
411 
412  // In some case, for example TParallelCoord, a list (the pad's list of
413  // primitives) will contain both the container and the containees
414  // (the TParallelCoorVar) but if the Clear is being called from
415  // the destructor of the container of this list, one of the first
416  // thing done will be the remove the container (the pad) for the
417  // list (of Primitives of the canvas) that was connecting it
418  // (indirectly) to the list of cleanups.
419  // So let's temporarily add the current list and remove it later.
420  bool needRegister = fFirst && TROOT::Initialized();
421  if(needRegister) {
423  needRegister = needRegister && !gROOT->GetListOfCleanups()->FindObject(this);
424  }
425  if (needRegister) {
427  gROOT->GetListOfCleanups()->Add(this);
428  }
429  while (fFirst) {
430  TObjLink *tlk = fFirst;
431  fFirst = fFirst->Next();
432  fSize--;
433  // delete only heap objects
434  if (tlk->GetObject() && tlk->GetObject()->IsOnHeap())
436  else if (tlk->GetObject() && tlk->GetObject()->IsA()->GetDirectoryAutoAdd())
437  removeDirectory.Add(tlk->GetObject());
438 
439  delete tlk;
440  }
441 
442  if (needRegister) {
445  }
446 
447  fFirst = fLast = fCache = 0;
448  fSize = 0;
449 
450  } else {
451 
452  TObjLink *first = fFirst; //pointer to first entry in linked list
453  fFirst = fLast = fCache = 0;
454  fSize = 0;
455  while (first) {
456  TObjLink *tlk = first;
457  first = first->Next();
458  // delete only heap objects
459  if (tlk->GetObject() && tlk->GetObject()->IsOnHeap())
461  else if (tlk->GetObject() && tlk->GetObject()->IsA()->GetDirectoryAutoAdd())
462  removeDirectory.Add(tlk->GetObject());
463 
464  delete tlk;
465  }
466  }
467 
468  // These objects cannot expect to have a valid TDirectory anymore;
469  // e.g. because *this is the TDirectory's list of objects. Even if
470  // not, they are supposed to be deleted, so we can as well unregister
471  // them from their directory, even if they are stack-based:
472  TIter iRemDir(&removeDirectory);
473  TObject* dirRem = 0;
474  while ((dirRem = iRemDir())) {
475  (*dirRem->IsA()->GetDirectoryAutoAdd())(dirRem, 0);
476  }
477  Changed();
478 }
479 
480 ////////////////////////////////////////////////////////////////////////////////
481 /// Delete a TObjLink object.
482 
484 {
485  lnk->fNext = lnk->fPrev = 0;
486  lnk->fObject = 0;
487  delete lnk;
488 }
489 
490 ////////////////////////////////////////////////////////////////////////////////
491 /// Find an object in this list using its name. Requires a sequential
492 /// scan till the object has been found. Returns 0 if object with specified
493 /// name is not found. This method overrides the generic FindObject()
494 /// of TCollection for efficiency reasons.
495 
496 TObject *TList::FindObject(const char *name) const
497 {
498  if (!name) return 0;
499  TObjLink *lnk = FirstLink();
500  while (lnk) {
501  TObject *obj = lnk->GetObject();
502  const char *objname = obj->GetName();
503  if (objname && !strcmp(name, objname)) return obj;
504  lnk = lnk->Next();
505  }
506  return 0;
507 }
508 
509 ////////////////////////////////////////////////////////////////////////////////
510 /// Find an object in this list using the object's IsEqual()
511 /// member function. Requires a sequential scan till the object has
512 /// been found. Returns 0 if object is not found.
513 /// This method overrides the generic FindObject() of TCollection for
514 /// efficiency reasons.
515 
517 {
518  TObjLink *lnk = FirstLink();
519 
520  while (lnk) {
521  TObject *ob = lnk->GetObject();
522  if (ob->IsEqual(obj)) return ob;
523  lnk = lnk->Next();
524  }
525  return 0;
526 }
527 
528 ////////////////////////////////////////////////////////////////////////////////
529 /// Returns the TObjLink object that contains object obj. In idx it returns
530 /// the position of the object in the list.
531 
532 TObjLink *TList::FindLink(const TObject *obj, Int_t &idx) const
533 {
534  if (!fFirst) return 0;
535 
536  TObject *object;
537  TObjLink *lnk = fFirst;
538  idx = 0;
539 
540  while (lnk) {
541  object = lnk->GetObject();
542  if (object) {
543  if (object->TestBit(kNotDeleted)) {
544  if (object->IsEqual(obj)) return lnk;
545  }
546  }
547  lnk = lnk->Next();
548  idx++;
549  }
550  return 0;
551 }
552 
553 ////////////////////////////////////////////////////////////////////////////////
554 /// Return the first object in the list. Returns 0 when list is empty.
555 
557 {
558  if (fFirst) return fFirst->GetObject();
559  return 0;
560 }
561 
562 ////////////////////////////////////////////////////////////////////////////////
563 /// Return address of pointer to obj
564 
566 {
567  TObjLink *lnk = FirstLink();
568 
569  while (lnk) {
570  TObject *ob = lnk->GetObject();
571  if (ob->IsEqual(obj)) return lnk->GetObjectRef();
572  lnk = lnk->Next();
573  }
574  return 0;
575 }
576 
577 ////////////////////////////////////////////////////////////////////////////////
578 /// Return the last object in the list. Returns 0 when list is empty.
579 
581 {
582  if (fLast) return fLast->GetObject();
583  return 0;
584 }
585 
586 ////////////////////////////////////////////////////////////////////////////////
587 /// Return the TObjLink object at index idx.
588 
590 {
591  Int_t i = 0;
592  TObjLink *lnk = fFirst;
593  while (i < idx && lnk) {
594  i++;
595  lnk = lnk->Next();
596  }
597  return lnk;
598 }
599 
600 ////////////////////////////////////////////////////////////////////////////////
601 /// Return a list iterator.
602 
604 {
605  return new TListIter(this, dir);
606 }
607 
608 ////////////////////////////////////////////////////////////////////////////////
609 /// Return a new TObjLink.
610 
612 {
613  if (prev)
614  return new TObjLink(obj, prev);
615  else
616  return new TObjLink(obj);
617 }
618 
619 ////////////////////////////////////////////////////////////////////////////////
620 /// Return a new TObjOptLink (a TObjLink that also stores the option).
621 
623 {
624  if (prev)
625  return new TObjOptLink(obj, prev, opt);
626  else
627  return new TObjOptLink(obj, opt);
628 }
629 
630 ////////////////////////////////////////////////////////////////////////////////
631 /// Remove object from this collection and recursively remove the object
632 /// from all other objects (and collections).
633 
635 {
636  if (!obj) return;
637 
638  TObjLink *lnk = fFirst;
639  TObjLink *next = 0;
640  while (lnk) {
641  next = lnk->Next();
642  TObject *ob = lnk->GetObject();
643  if (ob->TestBit(kNotDeleted)) {
644  if (ob->IsEqual(obj)) {
645  if (lnk == fFirst) {
646  fFirst = next;
647  if (lnk == fLast)
648  fLast = fFirst;
649  else
650  fFirst->fPrev = 0;
651  DeleteLink(lnk);
652  } else if (lnk == fLast) {
653  fLast = lnk->Prev();
654  fLast->fNext = 0;
655  DeleteLink(lnk);
656  } else {
657  lnk->Prev()->fNext = next;
658  lnk->Next()->fPrev = lnk->Prev();
659  DeleteLink(lnk);
660  }
661  fSize--;
662  fCache = 0;
663  Changed();
664  } else
665  ob->RecursiveRemove(obj);
666  }
667  lnk = next;
668  }
669 }
670 
671 ////////////////////////////////////////////////////////////////////////////////
672 /// Remove object from the list.
673 
675 {
676  if (!obj) return 0;
677 
678  Int_t idx;
679  TObjLink *lnk = FindLink(obj, idx);
680 
681  if (!lnk) return 0;
682 
683  // return object found, which may be (pointer wise) different than the
684  // input object (depending on what IsEqual() is doing)
685 
686  TObject *ob = lnk->GetObject();
687  if (lnk == fFirst) {
688  fFirst = lnk->Next();
689  if (lnk == fLast)
690  fLast = fFirst;
691  else
692  fFirst->fPrev = 0;
693  DeleteLink(lnk);
694  } else if (lnk == fLast) {
695  fLast = lnk->Prev();
696  fLast->fNext = 0;
697  DeleteLink(lnk);
698  } else {
699  lnk->Prev()->fNext = lnk->Next();
700  lnk->Next()->fPrev = lnk->Prev();
701  DeleteLink(lnk);
702  }
703  fSize--;
704  fCache = 0;
705  Changed();
706 
707  return ob;
708 }
709 
710 ////////////////////////////////////////////////////////////////////////////////
711 /// Remove object link (and therefore the object it contains)
712 /// from the list.
713 
715 {
716  if (!lnk) return 0;
717 
718  TObject *obj = lnk->GetObject();
719 
720  if (lnk == fFirst) {
721  fFirst = lnk->Next();
722  if (lnk == fLast)
723  fLast = fFirst;
724  else
725  fFirst->fPrev = 0;
726  DeleteLink(lnk);
727  } else if (lnk == fLast) {
728  fLast = lnk->Prev();
729  fLast->fNext = 0;
730  DeleteLink(lnk);
731  } else {
732  lnk->Prev()->fNext = lnk->Next();
733  lnk->Next()->fPrev = lnk->Prev();
734  DeleteLink(lnk);
735  }
736  fSize--;
737  fCache = 0;
738  Changed();
739 
740  return obj;
741 }
742 
743 ////////////////////////////////////////////////////////////////////////////////
744 /// Remove the last object of the list.
745 
747 {
748  TObjLink *lnk = fLast;
749  if (!lnk) return;
750 
751  if (lnk == fFirst) {
752  fFirst = 0;
753  fLast = 0;
754  } else {
755  fLast = lnk->Prev();
756  fLast->fNext = 0;
757  }
758  DeleteLink(lnk);
759 
760  fSize--;
761  fCache = 0;
762  Changed();
763 }
764 
765 ////////////////////////////////////////////////////////////////////////////////
766 /// Sort linked list. Real sorting is done in private function DoSort().
767 /// The list can only be sorted when is contains objects of a sortable
768 /// class.
769 
770 void TList::Sort(Bool_t order)
771 {
772  if (!fFirst) return;
773 
774  fAscending = order;
775 
776  if (!fFirst->GetObject()->IsSortable()) {
777  Error("Sort", "objects in list are not sortable");
778  return;
779  }
780 
781  DoSort(&fFirst, fSize);
782 
783  // correct back links
784  TObjLink *ol, *lnk = fFirst;
785 
786  if (lnk) lnk->fPrev = 0;
787  while ((ol = lnk)) {
788  lnk = lnk->fNext;
789  if (lnk)
790  lnk->fPrev = ol;
791  else
792  fLast = ol;
793  }
794  fSorted = kTRUE;
795 }
796 
797 ////////////////////////////////////////////////////////////////////////////////
798 /// Compares the objects stored in the TObjLink objects.
799 /// Depending on the flag IsAscending() the function returns
800 /// true if the object in l1 <= l2 (ascending) or l2 <= l1 (descending).
801 
803 {
804  Int_t cmp = l1->GetObject()->Compare(l2->GetObject());
805 
806  if ((IsAscending() && cmp <=0) || (!IsAscending() && cmp > 0))
807  return kTRUE;
808  return kFALSE;
809 }
810 
811 ////////////////////////////////////////////////////////////////////////////////
812 /// Sort linked list.
813 
815 {
816  TObjLink *p1, *p2, **h2, **t2;
817 
818  switch (n) {
819  case 0:
820  return head;
821 
822  case 1:
823  return &((*head)->fNext);
824 
825  case 2:
826  p2 = (p1 = *head)->fNext;
827  if (LnkCompare(p1, p2)) return &(p2->fNext);
828  p1->fNext = (*head = p2)->fNext;
829  return &((p2->fNext = p1)->fNext);
830  }
831 
832  int m;
833  n -= m = n / 2;
834 
835  t2 = DoSort(h2 = DoSort(head, n), m);
836 
837  if (LnkCompare((p1 = *head), (p2 = *h2))) {
838  do {
839  if (!--n) return *h2 = p2, t2;
840  } while (LnkCompare((p1 = *(head = &(p1->fNext))), p2));
841  }
842 
843  while (1) {
844  *head = p2;
845  do {
846  if (!--m) return *h2 = *t2, *t2 = p1, h2;
847  } while (!LnkCompare(p1, (p2 = *(head = &(p2->fNext)))));
848  *head = p1;
849  do {
850  if (!--n) return *h2 = p2, t2;
851  } while (LnkCompare((p1 = *(head = &(p1->fNext))), p2));
852  }
853 }
854 
855 /** \class TObjLink
856 Wrapper around a TObject so it can be stored in a TList.
857 */
858 
859 ////////////////////////////////////////////////////////////////////////////////
860 /// Create a new TObjLink.
861 
863  : fNext(prev->fNext), fPrev(prev), fObject(obj)
864 {
865  fPrev->fNext = this;
866  if (fNext) fNext->fPrev = this;
867 }
868 
869 /** \class TListIter
870 Iterator of linked list.
871 */
872 
874 
875 ////////////////////////////////////////////////////////////////////////////////
876 /// Create a new list iterator. By default the iteration direction
877 /// is kIterForward. To go backward use kIterBackward.
878 
879 TListIter::TListIter(const TList *l, Bool_t dir)
880  : fList(l), fCurCursor(0), fCursor(0), fDirection(dir), fStarted(kFALSE)
881 {
882 }
883 
884 ////////////////////////////////////////////////////////////////////////////////
885 /// Copy ctor.
886 
888 {
889  fList = iter.fList;
890  fCurCursor = iter.fCurCursor;
891  fCursor = iter.fCursor;
892  fDirection = iter.fDirection;
893  fStarted = iter.fStarted;
894 }
895 
896 ////////////////////////////////////////////////////////////////////////////////
897 /// Overridden assignment operator.
898 
900 {
901  const TListIter *rhs1 = dynamic_cast<const TListIter *>(&rhs);
902  if (this != &rhs && rhs1) {
904  fList = rhs1->fList;
905  fCurCursor = rhs1->fCurCursor;
906  fCursor = rhs1->fCursor;
907  fDirection = rhs1->fDirection;
908  fStarted = rhs1->fStarted;
909  }
910  return *this;
911 }
912 
913 ////////////////////////////////////////////////////////////////////////////////
914 /// Overloaded assignment operator.
915 
917 {
918  if (this != &rhs) {
920  fList = rhs.fList;
921  fCurCursor = rhs.fCurCursor;
922  fCursor = rhs.fCursor;
923  fDirection = rhs.fDirection;
924  fStarted = rhs.fStarted;
925  }
926  return *this;
927 }
928 
929 ////////////////////////////////////////////////////////////////////////////////
930 /// Return next object in the list. Returns 0 when no more objects in list.
931 
933 {
934  if (!fList) return 0;
935 
936  if (fDirection == kIterForward) {
937  if (!fStarted) {
938  fCursor = fList->fFirst;
939  fStarted = kTRUE;
940  }
942  if (fCursor) fCursor = fCursor->Next();
943  } else {
944  if (!fStarted) {
945  fCursor = fList->fLast;
946  fStarted = kTRUE;
947  }
949  if (fCursor) fCursor = fCursor->Prev();
950  }
951 
952  if (fCurCursor) return fCurCursor->GetObject();
953  return 0;
954 }
955 
956 ////////////////////////////////////////////////////////////////////////////////
957 /// Returns the object option stored in the list.
958 
960 {
961  if (fCurCursor) return fCurCursor->GetOption();
962  return "";
963 }
964 
965 ////////////////////////////////////////////////////////////////////////////////
966 /// Sets the object option stored in the list.
967 
969 {
970  if (fCurCursor) fCurCursor->SetOption(option);
971 }
972 
973 ////////////////////////////////////////////////////////////////////////////////
974 /// Reset list iterator.
975 
977 {
978  fStarted = kFALSE;
979 }
980 
981 ////////////////////////////////////////////////////////////////////////////////
982 /// This operator compares two TIterator objects.
983 
985 {
986  if (IsA() == aIter.IsA()) {
987  // We compared equal only two iterator of the same type.
988  // Since this is a function of TListIter, we consequently know that
989  // both this and aIter are of type inheriting from TListIter.
990  const TListIter &iter(dynamic_cast<const TListIter &>(aIter));
991  return (fCurCursor != iter.fCurCursor);
992  }
993  return false; // for base class we don't implement a comparison
994 }
995 
996 ////////////////////////////////////////////////////////////////////////////////
997 /// This operator compares two TListIter objects.
998 
1000 {
1001  return (fCurCursor != aIter.fCurCursor);
1002 }
1003 
1004 ////////////////////////////////////////////////////////////////////////////////
1005 /// Stream all objects in the collection to or from the I/O buffer.
1006 
1007 void TList::Streamer(TBuffer &b)
1008 {
1009  Int_t nobjects;
1010  UChar_t nch;
1011  Int_t nbig;
1012  TObject *obj;
1013  UInt_t R__s, R__c;
1014 
1015  if (b.IsReading()) {
1016  Clear(); // Get rid of old data if any.
1017  Version_t v = b.ReadVersion(&R__s, &R__c);
1018  if (v > 3) {
1019  TObject::Streamer(b);
1020  fName.Streamer(b);
1021  b >> nobjects;
1022  string readOption;
1023  for (Int_t i = 0; i < nobjects; i++) {
1024  b >> obj;
1025  b >> nch;
1026  if (v > 4 && nch == 255) {
1027  b >> nbig;
1028  } else {
1029  nbig = nch;
1030  }
1031  readOption.resize(nbig,'\0');
1032  b.ReadFastArray((char*) readOption.data(),nbig);
1033  if (obj) { // obj can be null if the class had a custom streamer and we do not have the shared library nor a streamerInfo.
1034  if (nch) {
1035  Add(obj,readOption.c_str());
1036  } else {
1037  Add(obj);
1038  }
1039  }
1040  }
1041  b.CheckByteCount(R__s, R__c,TList::IsA());
1042  return;
1043  }
1044 
1045  // process old versions when TList::Streamer was in TCollection::Streamer
1046  if (v > 2)
1047  TObject::Streamer(b);
1048  if (v > 1)
1049  fName.Streamer(b);
1050  b >> nobjects;
1051  for (Int_t i = 0; i < nobjects; i++) {
1052  b >> obj;
1053  Add(obj);
1054  }
1055  b.CheckByteCount(R__s, R__c,TList::IsA());
1056 
1057  } else {
1058  R__c = b.WriteVersion(TList::IsA(), kTRUE);
1059  TObject::Streamer(b);
1060  fName.Streamer(b);
1061  nobjects = GetSize();
1062  b << nobjects;
1063 
1064  TObjLink *lnk = fFirst;
1065  while (lnk) {
1066  obj = lnk->GetObject();
1067  b << obj;
1068 
1069  nbig = strlen(lnk->GetAddOption());
1070  if (nbig > 254) {
1071  nch = 255;
1072  b << nch;
1073  b << nbig;
1074  } else {
1075  nch = UChar_t(nbig);
1076  b << nch;
1077  }
1078  b.WriteFastArray(lnk->GetAddOption(),nbig);
1079 
1080  lnk = lnk->Next();
1081  }
1082  b.SetByteCount(R__c, kTRUE);
1083  }
1084 }
virtual TObject * Remove(TObject *obj)=0
virtual void AddAt(TObject *obj, Int_t idx)
Insert object at position idx in the list.
Definition: TList.cxx:268
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:404
virtual TObjLink * NewOptLink(TObject *obj, Option_t *opt, TObjLink *prev=NULL)
Return a new TObjOptLink (a TObjLink that also stores the option).
Definition: TList.cxx:622
Bool_t IsOnHeap() const
Definition: TObject.h:140
Bool_t fStarted
Definition: TList.h:197
TObjLink * LinkAt(Int_t idx) const
sorting order (when calling Sort() or for TSortedList)
Definition: TList.cxx:589
Bool_t IsReading() const
Definition: TBuffer.h:81
TObjLink * fCursor
Definition: TList.h:195
short Version_t
Definition: RtypesCore.h:61
ClassImp(TSeqCollection) Int_t TSeqCollection TIter next(this)
Return index of object in collection.
virtual void DeleteLink(TObjLink *lnk)
Delete a TObjLink object.
Definition: TList.cxx:483
const char Option_t
Definition: RtypesCore.h:62
virtual void RemoveLast()
Remove the last object of the list.
Definition: TList.cxx:746
virtual void AddFirst(TObject *obj)
Add object at the beginning of the list.
Definition: TList.cxx:92
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
const TList * fList
Definition: TList.h:193
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
#define gROOT
Definition: TROOT.h:340
TObject * ob
Option_t * GetOption() const
Returns the object option stored in the list.
Definition: TList.cxx:959
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:63
const Bool_t kFALSE
Definition: Rtypes.h:92
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:496
TString fName
Definition: TCollection.h:62
TObjLink * fCurCursor
Definition: TList.h:194
STL namespace.
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
virtual Bool_t IsEqual(const TObject *obj) const
Default equal comparison (objects are equal if they have the same address in memory).
Definition: TObject.cxx:527
TObject * Next()
Return next object in the list. Returns 0 when no more objects in list.
Definition: TList.cxx:932
virtual TObject * At(Int_t idx) const
Returns the object at position idx. Returns 0 if idx is out of range.
Definition: TList.cxx:310
Iterator abstract base class.
Definition: TIterator.h:32
Iterator of linked list.
Definition: TList.h:187
virtual void AddLast(TObject *obj)
Add object at the end of the list.
Definition: TList.cxx:136
virtual void RecursiveRemove(TObject *obj)
Recursively remove this object from a list.
Definition: TObject.cxx:616
virtual void Sort(Bool_t order=kSortAscending)
Sort linked list.
Definition: TList.cxx:770
virtual TObject * After(const TObject *obj) const
Returns the object after object obj.
Definition: TList.cxx:288
UChar_t mod R__LOCKGUARD2(gSrvAuthenticateMutex)
static Bool_t Initialized()
Return kTRUE if the TROOT object has been initialized.
Definition: TROOT.cxx:2469
std::map< std::string, std::string >::const_iterator iter
Definition: TAlienJob.cxx:54
static double p2(double t, double a, double b, double c)
Bool_t fDirection
Definition: TList.h:196
const Bool_t kIterForward
Definition: TCollection.h:43
Bool_t LnkCompare(TObjLink *l1, TObjLink *l2)
Compares the objects stored in the TObjLink objects.
Definition: TList.cxx:802
TSeqCollection * GetListOfCleanups() const
Definition: TROOT.h:232
void Error(const char *location, const char *msgfmt,...)
A doubly linked list.
Definition: TList.h:47
virtual TObject * Before(const TObject *obj) const
Returns the object before object obj.
Definition: TList.cxx:321
TListIter()
Definition: TList.h:199
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:674
TClass * IsA() const
TObjLink * fLast
pointer to first entry in linked list
Definition: TList.h:53
unsigned int UInt_t
Definition: RtypesCore.h:42
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:173
TMarker * m
Definition: textangle.C:8
TLine * l
Definition: textangle.C:4
virtual void SetByteCount(UInt_t cntpos, Bool_t packInVersion=kFALSE)=0
static double p1(double t, double a, double b)
TROOT * GetROOT()
Definition: TROOT.cxx:375
virtual void AddBefore(const TObject *before, TObject *obj)
Insert object before object before in the list.
Definition: TList.cxx:172
virtual void ReadFastArray(Bool_t *b, Int_t n)=0
virtual void WriteFastArray(const Bool_t *b, Int_t n)=0
TObjLink * fFirst
Definition: TList.h:52
static void GarbageCollect(TObject *obj)
Add to the list of things to be cleaned up.
virtual TObject * Last() const
Return the last object in the list. Returns 0 when list is empty.
Definition: TList.cxx:580
virtual Int_t GetSize() const
Definition: TCollection.h:95
Bool_t operator!=(const TIterator &aIter) const
This operator compares two TIterator objects.
Definition: TList.cxx:984
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:415
virtual void Clear(Option_t *option="")
Remove all objects from the list.
Definition: TList.cxx:348
void SetOption(Option_t *option)
Sets the object option stored in the list.
Definition: TList.cxx:968
virtual void AddAfter(const TObject *after, TObject *obj)
Insert object after object after in the list.
Definition: TList.cxx:220
#define name(a, b)
Definition: linkTestLib0.cpp:5
Mother of all ROOT objects.
Definition: TObject.h:58
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition: TList.cxx:556
TObjLink ** DoSort(TObjLink **head, Int_t n)
Sort linked list.
Definition: TList.cxx:814
virtual void Add(TObject *obj)
Definition: TList.h:81
virtual void RecursiveRemove(TObject *obj)
Remove object from this collection and recursively remove the object from all other objects (and coll...
Definition: TList.cxx:634
TObjLink * FindLink(const TObject *obj, Int_t &idx) const
Returns the TObjLink object that contains object obj.
Definition: TList.cxx:532
virtual TIterator & operator=(const TIterator &)
Definition: TIterator.h:39
virtual Int_t Compare(const TObject *obj) const
Compare abstract method.
Definition: TObject.cxx:218
void Reset()
Reset list iterator.
Definition: TList.cxx:976
virtual TIterator * MakeIterator(Bool_t dir=kIterForward) const
Return a list iterator.
Definition: TList.cxx:603
virtual TObject ** GetObjectRef(const TObject *obj) const
Return address of pointer to obj.
Definition: TList.cxx:565
virtual TObjLink * NewLink(TObject *obj, TObjLink *prev=NULL)
Return a new TObjLink.
Definition: TList.cxx:611
unsigned char UChar_t
Definition: RtypesCore.h:34
TIterator & operator=(const TIterator &rhs)
Overridden assignment operator.
Definition: TList.cxx:899
const Bool_t kTRUE
Definition: Rtypes.h:91
TObject * obj
ClassImp(TList) TList
Delete the list.
Definition: TList.cxx:78
const Int_t n
Definition: legend1.C:16
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
T1 fFirst
Definition: X11Events.mm:85