Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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
14Sequenceable collection abstract base class. TSeqCollection's have
15an 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 && !b) return 0;
59 if (!a) return 1;
60 if (!b) 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);
199 TObject *objtomerge;
200 TObject *collcrt;
201 TSeqCollection *templist = nullptr;
202 TMethodCall callEnv;
203 Int_t indobj = 0;
204 TSeqCollection *notmergeable = nullptr;
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 = nullptr;
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((Longptr_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 while (auto onm = nxnm())
286 Add(onm->Clone());
287 SafeDelete(notmergeable);
288 }
289
290 return nmerged;
291}
#define SafeDelete(p)
Definition RConfig.hxx:525
#define b(i)
Definition RSha256.hxx:100
#define a(i)
Definition RSha256.hxx:99
long Longptr_t
Definition RtypesCore.h:82
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
long long Long64_t
Definition RtypesCore.h:80
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
#define ClassImp(name)
Definition Rtypes.h:377
R__EXTERN TVirtualMutex * gCollectionMutex
Definition TCollection.h:45
#define R__LOCKGUARD2(mutex)
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition TClass.cxx:4978
Collection abstract base class.
Definition TCollection.h:65
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
virtual Bool_t IsEmpty() const
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
void Reset()
Method or function calling interface.
Definition TMethodCall.h:37
void Execute(const char *, const char *, int *=nullptr) override
Execute method on this object with the given parameter string, e.g.
Definition TMethodCall.h:64
Bool_t IsValid() const
Return true if the method call has been properly initialized and is usable.
void InitWithPrototype(TClass *cl, const char *method, const char *proto, Bool_t objectIsConst=kFALSE, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch)
Initialize the method invocation environment.
void SetParam(Long_t l)
Add a long method parameter.
Mother of all ROOT objects.
Definition TObject.h:41
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:565
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:207
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:973
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:525
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:987
virtual TClass * IsA() const
Definition TObject.h:243
Sequenceable collection abstract base class.
Int_t LastIndex() const
virtual Int_t IndexOf(const TObject *obj) const
Return index of object in collection.
static TClass * Class()
TClass * IsA() const override
virtual TObject * Last() const =0
static void QSort(TObject **a, Int_t first, Int_t last)
Sort array of TObject pointers using a quicksort algorithm.
Long64_t Merge(TCollection *list)
Merge this collection with all collections coming in the input list.
virtual Int_t GetLast() const
Returns index of last object in collection.
static Int_t ObjCompare(TObject *a, TObject *b)
Compare to objects in the collection. Use member Compare() of object a.
void Add(TObject *obj) override