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