Logo ROOT   6.12/07
Reference Guide
TSeqCollection.cxx
Go to the documentation of this file.
1 // @(#)root/cont:$Id$
2 // Author: Fons Rademakers 04/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 TSeqCollection
13 \ingroup Containers
14 Sequenceable collection abstract base class. TSeqCollection's have
15 an ordering relation, i.e. there is a first and last element.
16 */
17 
18 #include "TSeqCollection.h"
19 #include "TCollection.h"
20 #include "TVirtualMutex.h"
21 #include "TClass.h"
22 #include "TMethodCall.h"
23 
25 
26 ////////////////////////////////////////////////////////////////////////////////
27 /// Return index of object in collection. Returns -1 when object not found.
28 /// Uses member IsEqual() to find object.
29 
31 {
32  Int_t idx = 0;
33  TIter next(this);
34  TObject *ob;
35 
36  while ((ob = next())) {
37  if (ob->IsEqual(obj)) return idx;
38  idx++;
39  }
40  return -1;
41 }
42 
43 ////////////////////////////////////////////////////////////////////////////////
44 /// Returns index of last object in collection. Returns -1 when no
45 /// objects in collection.
46 
48 {
49  TObject *tmp = Last();
50  return tmp ? IndexOf(tmp) : -1;
51 }
52 
53 ////////////////////////////////////////////////////////////////////////////////
54 /// Compare to objects in the collection. Use member Compare() of object a.
55 
57 {
58  if (a == 0 && b == 0) return 0;
59  if (a == 0) return 1;
60  if (b == 0) return -1;
61  return a->Compare(b);
62 }
63 
64 ////////////////////////////////////////////////////////////////////////////////
65 /// Sort array of TObject pointers using a quicksort algorithm.
66 /// The algorithm used is a non stable sort (i.e. already sorted
67 /// elements might switch/change places).
68 /// Uses ObjCompare() to compare objects.
69 
71 {
73 
74  static TObject *tmp;
75  static int i; // "static" to save stack space
76  int j;
77 
78  while (last - first > 1) {
79  i = first;
80  j = last;
81  for (;;) {
82  while (++i < last && ObjCompare(a[i], a[first]) < 0)
83  ;
84  while (--j > first && ObjCompare(a[j], a[first]) > 0)
85  ;
86  if (i >= j)
87  break;
88 
89  tmp = a[i];
90  a[i] = a[j];
91  a[j] = tmp;
92  }
93  if (j == first) {
94  ++first;
95  continue;
96  }
97  tmp = a[first];
98  a[first] = a[j];
99  a[j] = tmp;
100  if (j - first < last - (j + 1)) {
101  QSort(a, first, j);
102  first = j + 1; // QSort(j + 1, last);
103  } else {
104  QSort(a, j + 1, last);
105  last = j; // QSort(first, j);
106  }
107  }
108 }
109 
110 ////////////////////////////////////////////////////////////////////////////////
111 /// Sort array a of TObject pointers using a quicksort algorithm.
112 /// Arrays b will be sorted just like a (a determines the sort).
113 /// Argument nBs is the number of TObject** arrays in b.
114 /// The algorithm used is a non stable sort (i.e. already sorted
115 /// elements might switch/change places).
116 /// Uses ObjCompare() to compare objects.
117 
119 {
121 
122  static TObject *tmp1, **tmp2;
123  static int i; // "static" to save stack space
124  int j,k;
125 
126  static int depth = 0;
127  if (depth == 0 && nBs > 0) tmp2 = new TObject*[nBs];
128  depth++;
129 
130  while (last - first > 1) {
131  i = first;
132  j = last;
133  for (;;) {
134  while (++i < last && ObjCompare(a[i], a[first]) < 0) {}
135  while (--j > first && ObjCompare(a[j], a[first]) > 0) {}
136  if (i >= j) break;
137 
138  tmp1 = a[i]; for(k=0;k<nBs;k++) tmp2[k] = b[k][i];
139  a[i] = a[j]; for(k=0;k<nBs;k++) b[k][i] = b[k][j];
140  a[j] = tmp1; for(k=0;k<nBs;k++) b[k][j] = tmp2[k];
141  }
142  if (j == first) {
143  ++first;
144  continue;
145  }
146  tmp1 = a[first]; for(k=0;k<nBs;k++) tmp2[k] = b[k][first];
147  a[first] = a[j]; for(k=0;k<nBs;k++) b[k][first] = b[k][j];
148  a[j] = tmp1; for(k=0;k<nBs;k++) b[k][j] = tmp2[k];
149  if (j - first < last - (j + 1)) {
150  QSort(a, nBs, b, first, j);
151  first = j + 1; // QSort(j + 1, last);
152  } else {
153  QSort(a, nBs, b, j + 1, last);
154  last = j; // QSort(first, j);
155  }
156  }
157  depth--;
158 
159  if (depth == 0 && nBs > 0) delete [] tmp2;
160 }
161 
162 ////////////////////////////////////////////////////////////////////////////////
163 /// Merge this collection with all collections coming in the input list. The
164 /// input list must contain other collections of objects compatible with the
165 /// ones in this collection and ordered in the same manner. For example, if this
166 /// collection contains a TH1 object and a tree, all collections in the input
167 /// list have to contain a histogram and a tree. In case the list contains
168 /// collections, the objects in the input lists must also be collections with
169 /// the same structure and number of objects.
170 /// If some objects inside the collection are instances of a class that do not
171 /// have a Merge function (like TObjString), rather than merging, a copy of each
172 /// instance (via a call to Clone) is appended to the output.
173 ///
174 /// ### Example
175 /// ~~~ {.cpp}
176 /// this list
177 /// ____________ ---------------------|
178 /// | A (TH1F) | __________ | L1 (TSeqCollection)|- [A1, B1(C1,D1,E1)]
179 /// | B (TList)|-| C (TTree)| | L1 (TSeqCollection)|- [A2, B2(C2,D2,E2)]
180 /// |__________| | D (TH1F) | | ... |- [...]
181 /// | E (TH1F) | |____________________|
182 /// |__________|
183 /// ~~~
184 
186 {
187  Long64_t nmerged = 0;
188  if (IsEmpty() || !list) {
189  Warning("Merge", "list is empty - nothing to merge");
190  return 0;
191  }
192  if (list->IsEmpty()) {
193  Warning("Merge", "input list is empty - nothing to merge with");
194  return 0;
195  }
196  TIter nextobject(this);
197  TIter nextlist(list);
198  TObject *object;
199  TObject *objtomerge;
200  TObject *collcrt;
201  TSeqCollection *templist = 0;
202  TMethodCall callEnv;
203  Int_t indobj = 0;
204  TSeqCollection *notmergeable = 0;
205  Bool_t mergeable = kTRUE;
206  while ((object = nextobject())) { // loop objects in this collection
207  mergeable = kTRUE;
208  // If current object has not dictionary just add it
209  if (!object->IsA()) {
210  mergeable = kFALSE;
211  } else {
212  // If current object is not mergeable just add it
213  callEnv.InitWithPrototype(object->IsA(), "Merge", "TCollection*");
214  if (!callEnv.IsValid()) mergeable = kFALSE;
215  }
216  if (mergeable) {
217  // Current object mergeable - get corresponding objects in input lists
218  templist = (TSeqCollection*)IsA()->New();
219  // Make sure original objects are not deleted; some containers, e.g. TSelectorList, maybe owners
220  templist->SetOwner(kFALSE);
221  } else {
222  templist = 0;
223  }
224  nextlist.Reset();
225  Int_t indcoll = 0;
226  while ((collcrt = nextlist())) { // loop input lists
227  if (!collcrt->InheritsFrom(TSeqCollection::Class())) {
228  Error("Merge", "some objects in the input list are not collections - merging aborted");
229  SafeDelete(templist);
230  return 0;
231  }
232  if (indobj > ((TSeqCollection*)collcrt)->LastIndex()) {
233  // We reached the end of this collection.
234  continue;
235  }
236  // The next object to be merged with is a collection
237  // the iterator skips the 'holes' the collections, we also need to do so.
238  objtomerge = ((TSeqCollection*)collcrt)->At(indobj);
239  if (!objtomerge) {
240  Warning("Merge", "object of type %s (position %d in list) not found in list %d. Continuing...",
241  object->ClassName(), indobj, indcoll);
242  continue;
243  }
244 /*
245  // Dangerous - may try to merge non-corresponding histograms (A.G)
246  while (objtomerge == 0
247  && indobj < ((TSeqCollection*)collcrt)->LastIndex()
248  ) {
249  ++indobj;
250  objtomerge = ((TSeqCollection*)collcrt)->At(indobj);
251  }
252 */
253  if (object->IsA() != objtomerge->IsA()) {
254  Error("Merge", "object of type %s at index %d not matching object of type %s in input list",
255  object->ClassName(), indobj, objtomerge->ClassName());
256  SafeDelete(templist);
257  return 0;
258  }
259  // Add object at index indobj in the temporary list
260  if (mergeable) {
261  templist->Add(objtomerge);
262  nmerged++;
263  } else {
264  // Just add it to the dedicated temp list for later addition to the current list
265  if (!notmergeable && IsA())
266  notmergeable = (TSeqCollection*)IsA()->New();
267  if (notmergeable)
268  notmergeable->Add(objtomerge);
269  else
270  Warning("Merge", "temp list for non mergeable objects not created!");
271  }
272  }
273  // Merge current object with objects in the temporary list
274  if (mergeable) {
275  callEnv.SetParam((Long_t) templist);
276  callEnv.Execute(object);
277  SafeDelete(templist);
278  }
279  indobj++;
280  }
281 
282  // Add the non-mergeable objects, if any
283  if (notmergeable && notmergeable->GetSize() > 0) {
284  TIter nxnm(notmergeable);
285  TObject *onm = 0;
286  while ((onm = nxnm())) { Add(onm->Clone()); }
287  SafeDelete(notmergeable);
288  }
289 
290  return nmerged;
291 }
virtual void Add(TObject *obj)
long long Long64_t
Definition: RtypesCore.h:69
R__EXTERN TVirtualMutex * gCollectionMutex
Definition: TCollection.h:43
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
void Reset()
Definition: TCollection.h:250
#define SafeDelete(p)
Definition: RConfig.h:509
Sequenceable collection abstract base class.
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:128
void Class()
Definition: Class.C:29
Method or function calling interface.
Definition: TMethodCall.h:37
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:483
auto * a
Definition: textangle.C:12
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
Collection abstract base class.
Definition: TCollection.h:63
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
virtual Int_t Compare(const TObject *obj) const
Compare abstract method.
Definition: TObject.cxx:159
static void QSort(TObject **a, Int_t first, Int_t last)
Sort array of TObject pointers using a quicksort algorithm.
Bool_t IsValid() const
Return true if the method call has been properly initialized and is usable.
Int_t LastIndex() const
void InitWithPrototype(TClass *cl, const char *method, const char *proto, Bool_t objectIsConst=kFALSE, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch)
Initialize the method invocation environment.
#define R__LOCKGUARD2(mutex)
const Bool_t kFALSE
Definition: RtypesCore.h:88
long Long_t
Definition: RtypesCore.h:50
virtual Bool_t IsEmpty() const
Definition: TCollection.h:184
#define ClassImp(name)
Definition: Rtypes.h:359
Mother of all ROOT objects.
Definition: TObject.h:37
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition: TObject.cxx:144
void Execute(const char *, const char *, int *=0)
Execute method on this object with the given parameter string, e.g.
Definition: TMethodCall.h:64
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
void SetParam(Long_t l)
Add a long method parameter.
virtual Int_t GetLast() const
Returns index of last object in collection.
Definition: first.py:1
virtual Int_t GetSize() const
Definition: TCollection.h:180
static Int_t ObjCompare(TObject *a, TObject *b)
Compare to objects in the collection. Use member Compare() of object a.
const Bool_t kTRUE
Definition: RtypesCore.h:87
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
Long64_t Merge(TCollection *list)
Merge this collection with all collections coming in the input list.
virtual TObject * Last() const =0
virtual Int_t IndexOf(const TObject *obj) const
Return index of object in collection.