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