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