Logo ROOT  
Reference Guide
TOutputListSelectorDataMap.cxx
Go to the documentation of this file.
1// @(#)root/proofplayer:$Id$
2// Author: Axel Naumann, 2010-06-09
3
4/*************************************************************************
5 * Copyright (C) 1995-2010, 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 TOutputListSelectorDataMap
13\ingroup proofkernel
14
15Set the selector's data members to the corresponding elements of the
16output list.
17
18*/
19
21
22#include "TClass.h"
23#include "TDataMember.h"
24#include "TExMap.h"
25#include "THashTable.h"
26#include "TList.h"
27#include "TMemberInspector.h"
28#include "TProofDebug.h"
29#include "TSelector.h"
30
31#include <cstddef>
32
33namespace {
34
35 static TClass* IsSettableDataMember(TDataMember* dm) {
36 if (!dm || !dm->IsaPointer() || dm->IsBasic()) return 0;
37 TString dtTypeName = dm->GetFullTypeName();
38 if (!dtTypeName.EndsWith("*")) return 0;
39 dtTypeName.Remove(dtTypeName.Length()-1);
40 return TClass::GetClass(dtTypeName);
41 }
42
43 class TSetSelDataMembers: public TMemberInspector {
44 public:
45 TSetSelDataMembers(const TOutputListSelectorDataMap& owner, TCollection* dmInfo, TList* output);
47 void Inspect(TClass *cl, const char *parent, const char *name, const void *addr, Bool_t isTransient);
48 Ssiz_t GetNumSet() const { return fNumSet; }
49 private:
50 TCollection* fDMInfo; // output list object name / member name pairs for output list entries
51 TList* fOutputList; // merged output list
52 Ssiz_t fNumSet; // number of initialized data members
53 const TOutputListSelectorDataMap& fOwner; // owner, used for messaging
54 };
55}
56
57////////////////////////////////////////////////////////////////////////////////
58
59TSetSelDataMembers::TSetSelDataMembers(const TOutputListSelectorDataMap& owner,
60 TCollection* dmInfo, TList* output):
61 fDMInfo(dmInfo), fOutputList(output), fNumSet(0), fOwner(owner)
62{}
63
64////////////////////////////////////////////////////////////////////////////////
65/// This method is called by the ShowMembers() method for each
66/// data member to recursively collect all base classes' members.
67///
68/// cl is the pointer to the current class
69/// parent is the parent name (in case of composed objects)
70/// name is the data member name
71/// addr is the data member address
72
73void TSetSelDataMembers::Inspect(TClass *cl, const char* parent, const char *name, const void *addr, Bool_t /* isTransient */)
74{
75 while (name[0] == '*') ++name;
76
77 TObject* mapping = fDMInfo->FindObject(name);
78 if (!mapping) return;
79
80 PDB(kOutput,1) fOwner.Info("SetDataMembers()",
81 "data member `%s%s::%s' maps to output list object `%s'",
82 cl->GetName(), parent, name, mapping->GetTitle());
83
84 TObject* outputObj = fOutputList->FindObject(mapping->GetTitle());
85 if (!outputObj) {
86 PDB(kOutput,1) fOwner.Warning("SetDataMembers()",
87 "object `%s' not found in output list!",
88 mapping->GetTitle());
89 return;
90 }
91
92 // Check data member type
93 TDataMember *dm = cl->GetDataMember(name);
94 TClass* cldt = IsSettableDataMember(dm);
95 if (!cldt) {
96 PDB(kOutput,1) fOwner.Warning("SetDataMembers()",
97 "unusable data member `%s' should have been detected by TCollectDataMembers!",
98 name);
99 return;
100 }
101
102 char *pointer = (char*)addr;
103 char **ppointer = (char**)(pointer);
104 if (*ppointer) {
105 // member points to something - replace instead of delete to not crash on deleting uninitialized values.
106 fOwner.Warning("SetDataMembers()", "potential memory leak: replacing data member `%s' != 0. "
107 "Please initialize %s to 0 in constructor %s::%s()",
108 name, name, cl->GetName(), cl->GetName());
109 }
110 *ppointer = (char*)outputObj;
111 ++fNumSet;
112}
113
114
115namespace {
116 class TCollectDataMembers: public TMemberInspector {
117 public:
118 TCollectDataMembers(const TOutputListSelectorDataMap& owner): fOwner(owner) { }
119 ~TCollectDataMembers();
121 void Inspect(TClass *cl, const char *parent, const char *name, const void *addr, Bool_t isTransient);
122 TExMap& GetMemberPointers() { return fMap; }
123 private:
124 TExMap fMap; //map of data member's value to TDataMember
125 const TOutputListSelectorDataMap& fOwner; //owner, used for messaging
126 };
127}
128
129////////////////////////////////////////////////////////////////////////////////
130/// This method is called by the ShowMembers() method for each
131/// data member to recursively collect all base classes' members.
132///
133/// cl is the pointer to the current class
134/// parent is the parent name (in case of composed objects)
135/// name is the data member name
136/// addr is the data member address
137
138void TCollectDataMembers::Inspect(TClass *cl, const char* /*parent*/, const char *name, const void *addr, Bool_t /* isTransient */)
139{
140 TDataMember *dm = cl->GetDataMember(name);
141 if (!IsSettableDataMember(dm)) return;
142
143 char *pointer = (char*)addr;
144 char **ppointer = (char**)(pointer);
145 char **p3pointer = (char**)(*ppointer);
146 if (p3pointer) {
147 // The data member points to something.
148 // Handle multiple pointers to the same output list object:
149 TObject* prev = (TObject*) (ptrdiff_t)fMap.GetValue((Long64_t)(ptrdiff_t)p3pointer);
150 if (prev) {
151 // We have a previous entry - is it a data member or already a TList (of data members)?
152 if (prev->InheritsFrom(TDataMember::Class())) {
153 fMap.Remove((Long64_t)(ptrdiff_t)p3pointer);
154 TList* dmList = new TList;
155 dmList->Add(prev);
156 dmList->Add(dm);
157 fMap.Add((Long64_t)(ptrdiff_t)p3pointer, (Long64_t)(ptrdiff_t)dmList);
158 } else {
159 TList* prevList = (TList*) prev;
160 prevList->Add(dm);
161 }
162 } else {
163 fMap.Add((Long64_t)(ptrdiff_t)p3pointer, (Long64_t)(ptrdiff_t)dm);
164 }
165 if (name[0] == '*') ++name;
166 PDB(kOutput,1) fOwner.Info("Init()", "considering data member `%s'", name);
167 }
168}
169
170TCollectDataMembers::~TCollectDataMembers() {
171 // Destructor
172
173 // Clean up collection of TDataMembers in fMap
174 TExMapIter iMembers(&fMap);
175 Long64_t key;
176 Long64_t value;
177 while (iMembers.Next(key, value)) {
178 TObject* obj = (TObject*) (ptrdiff_t) value;
179 if (obj->InheritsFrom(TList::Class())) {
180 delete obj;
181 }
182 }
183}
184
186
187////////////////////////////////////////////////////////////////////////////////
188/// Create a mapper between output list items and TSelector data members.
189
191 fMap(0)
192{
193 if (sel) Init(sel);
194}
195
196////////////////////////////////////////////////////////////////////////////////
197/// Return static name for TOutputListSelectorDataMap objects.
198
200{
201 return "PROOF_TOutputListSelectorDataMap_object";
202}
203
204////////////////////////////////////////////////////////////////////////////////
205/// Initialize the data member <-> output list mapping from a selector.
206
208{
209 if (!sel) {
210 PDB(kOutput,1) Warning("Init","Leave (no selector!)");
211 return kFALSE;
212 }
213 TCollection* outList = sel->GetOutputList();
214 if (!outList) {
215 PDB(kOutput,1) Info("Init()","Leave (no output)");
216 return kFALSE;
217 }
218
219 if (outList->FindObject(GetName())) {
220 // mapping already exists?!
221 PDB(kOutput,1) Warning("Init","Mapping already exists!");
222 return kFALSE;
223 }
224
225 if (fMap) delete fMap;
226 fMap = new THashTable;
227 fMap->SetOwner();
228
229 TCollectDataMembers cdm(*this);
230 if (!sel->IsA()->CallShowMembers(sel, cdm)) {
231 // failed to map
232 PDB(kOutput,1) Warning("Init","Failed to determine mapping!");
233 return kFALSE;
234 }
235 PDB(kOutput,1) Info("Init()","Found %d data members.",
236 cdm.GetMemberPointers().GetSize());
237
238 // Iterate over output list entries and find data members pointing to the
239 // same value. Store that mapping (or a miss).
240 TIter iOutput(outList);
242 TList oneDM;
243 while ((output = iOutput())) {
244 TObject* obj = (TObject*) (ptrdiff_t)cdm.GetMemberPointers().GetValue((Long64_t)(ptrdiff_t)output);
245 if (!obj) continue;
246
247 TList* addAllDM = 0;
248 if (obj->InheritsFrom(TDataMember::Class())) {
249 oneDM.Add(obj);
250 addAllDM = &oneDM;
251 } else {
252 addAllDM = (TList*) obj;
253 }
254 TIter iDM(addAllDM);
255 TDataMember* dm = 0;
256 while ((dm = (TDataMember*) iDM())) {
257 fMap->Add(new TNamed(dm->GetName(), output->GetName()));
258 PDB(kOutput,1) Info("Init()","Data member `%s' corresponds to output `%s'",
259 dm->GetName(), output->GetName());
260 }
261 oneDM.Clear();
262 }
263
264 return kTRUE;
265}
266
267////////////////////////////////////////////////////////////////////////////////
268/// Given an output list, set the data members of a TSelector.
269
271{
272 TList* output = sel->GetOutputList();
273 if (!output || output->IsEmpty()) return kTRUE;
274
275 // Set fSelector's data members
276 TSetSelDataMembers ssdm(*this, fMap, output);
277 Bool_t res = sel->IsA()->CallShowMembers(sel, ssdm);
278 PDB(kOutput,1) Info("SetDataMembers()","%s, set %d data members.",
279 (res ? "success" : "failure"), ssdm.GetNumSet());
280 return res;
281}
282
283////////////////////////////////////////////////////////////////////////////////
284/// Merge another TOutputListSelectorDataMap object, check
285/// consistency.
286
288{
289 TOutputListSelectorDataMap* other = dynamic_cast<TOutputListSelectorDataMap*>(obj);
290 if (!other) return kFALSE;
291
292 // check for consistency
293 TIter iMapping(other->GetMap());
294 TNamed* mapping = 0;
295 while ((mapping = (TNamed*)iMapping())) {
296 TObject* oldMap = fMap->FindObject(mapping->GetName());
297 if (!oldMap) {
298 fMap->Add(new TNamed(*mapping));
299 } else {
300 if (strcmp(oldMap->GetTitle(), mapping->GetTitle())) {
301 // ouch, contradicting maps!
302 PDB(kOutput,1)
303 Warning("Merge()",
304 "contradicting mapping for data member `%s' (output list entry `%s' vs. `%s'). "
305 "Cancelling automatic TSelector data member setting!",
306 mapping->GetName(), oldMap->GetTitle(), mapping->GetTitle());
307 fMap->Clear();
308 return kFALSE;
309 }
310 }
311 }
312 return kTRUE;
313}
314
315////////////////////////////////////////////////////////////////////////////////
316/// Find a TOutputListSelectorDataMap in a collection
317
319{
320 TIter iOutput(coll);
321 TObject* out = 0;
323 while ((out = iOutput())) {
325 olsdm = dynamic_cast<TOutputListSelectorDataMap*>(out);
326 if (olsdm) break;
327 }
328 }
329 return olsdm;
330}
void Class()
Definition: Class.C:29
int Ssiz_t
Definition: RtypesCore.h:65
const Bool_t kFALSE
Definition: RtypesCore.h:90
bool Bool_t
Definition: RtypesCore.h:61
long long Long64_t
Definition: RtypesCore.h:71
const Bool_t kTRUE
Definition: RtypesCore.h:89
#define ClassImp(name)
Definition: Rtypes.h:361
void Info(const char *location, const char *msgfmt,...)
void Warning(const char *location, const char *msgfmt,...)
char name[80]
Definition: TGX11.cxx:109
#define PDB(mask, level)
Definition: TProofDebug.h:56
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:80
TDataMember * GetDataMember(const char *datamember) const
Return pointer to datamember object with name "datamember".
Definition: TClass.cxx:3374
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2937
Collection abstract base class.
Definition: TCollection.h:63
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
virtual void Clear(Option_t *option="")=0
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
virtual void Add(TObject *obj)=0
All ROOT classes may have RTTI (run time type identification) support added.
Definition: TDataMember.h:31
Bool_t IsBasic() const
Return true if data member is a basic type, e.g. char, int, long...
Bool_t IsaPointer() const
Return true if data member is a pointer.
const char * GetFullTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
This class stores a (key,value) pair using an external hash.
Definition: TExMap.h:33
THashTable implements a hash table to store TObject's.
Definition: THashTable.h:35
A doubly linked list.
Definition: TList.h:44
virtual void Add(TObject *obj)
Definition: TList.h:87
virtual void Clear(Option_t *option="")
Remove all objects from the list.
Definition: TList.cxx:401
Abstract base class for accessing the data-members of a class.
virtual void Inspect(TClass *cl, const char *parent, const char *name, const void *addr)
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
Mother of all ROOT objects.
Definition: TObject.h:37
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:877
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition: TObject.cxx:321
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
virtual const char * GetTitle() const
Returns title of object.
Definition: TObject.cxx:401
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:865
Set the selector's data members to the corresponding elements of the output list.
Bool_t Merge(TObject *obj)
Merge another TOutputListSelectorDataMap object, check consistency.
static TOutputListSelectorDataMap * FindInList(TCollection *coll)
Find a TOutputListSelectorDataMap in a collection.
TOutputListSelectorDataMap(TSelector *sel=0)
Create a mapper between output list items and TSelector data members.
Bool_t SetDataMembers(TSelector *sel) const
Given an output list, set the data members of a TSelector.
Bool_t Init(TSelector *sel)
Initialize the data member <-> output list mapping from a selector.
const char * GetName() const
Return static name for TOutputListSelectorDataMap objects.
A TSelector object is used by the TTree::Draw, TTree::Scan, TTree::Process to navigate in a TTree and...
Definition: TSelector.h:33
virtual TList * GetOutputList() const
Definition: TSelector.h:71
Basic string class.
Definition: TString.h:131
Ssiz_t Length() const
Definition: TString.h:405
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2177
TString & Remove(Ssiz_t pos)
Definition: TString.h:668
void Init(TClassEdit::TInterpreterLookupHelper *helper)
Definition: TClassEdit.cxx:154
static constexpr double s
static void output(int code)
Definition: gifencode.c:226