source: trunk/MagicSoft/Mars/mbase/MParContainer.cc@ 1775

Last change on this file since 1775 was 1574, checked in by tbretz, 22 years ago
*** empty log message ***
File size: 13.1 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Thomas Bretz 12/2000 <mailto:tbretz@uni-sw.gwdg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2002
21!
22!
23\* ======================================================================== */
24
25//////////////////////////////////////////////////////////////////////////////
26// //
27// MParContainer //
28// //
29// The MParContainer class is the base class for all MARS parameter //
30// containers. At the moment it is almost the same than ROOT's TNamed. //
31// A TNamed contains the essential elements (name, title) //
32// to identify a derived object in lists like our MParList or MTaskList. //
33// The main difference is that the name and title isn't stored and read //
34// to and from root files ("//!") //
35// //
36//////////////////////////////////////////////////////////////////////////////
37#include "MParContainer.h"
38
39#include <ctype.h> // isdigit
40#include <fstream.h> // ofstream, AsciiWrite
41
42#include <TROOT.h> // TROOT::Identlevel
43#include <TClass.h> // IsA
44#include <TObjArray.h> // TObjArray
45#include <TBaseClass.h> // GetClassPointer
46#include <TMethodCall.h> // TMethodCall, AsciiWrite
47#include <TDataMember.h> // TDataMember, AsciiWrite
48#include <TVirtualPad.h> // gPad
49
50#include "MLog.h"
51#include "MLogManip.h"
52
53#include "MEvtLoop.h" // gListOfPrimitives
54
55ClassImp(MParContainer);
56
57// --------------------------------------------------------------------------
58//
59// MParContainer copy ctor
60//
61MParContainer::MParContainer(const MParContainer &named)
62{
63 fName = named.fName;
64 fTitle = named.fTitle;
65
66 fLog = named.fLog;
67
68 fReadyToSave = named.fReadyToSave;
69}
70
71// --------------------------------------------------------------------------
72//
73// MParContainer assignment operator.
74//
75MParContainer& MParContainer::operator=(const MParContainer& rhs)
76{
77 if (this == &rhs)
78 return *this;
79
80 TObject::operator=(rhs);
81
82 fName = rhs.fName;
83 fTitle = rhs.fTitle;
84
85 fLog = rhs.fLog;
86 fReadyToSave = rhs.fReadyToSave;
87
88 return *this;
89}
90
91// --------------------------------------------------------------------------
92//
93// Make a clone of an object using the Streamer facility.
94// If newname is specified, this will be the name of the new object
95//
96TObject *MParContainer::Clone(const char *newname) const
97{
98
99 MParContainer *named = (MParContainer*)TObject::Clone();
100 if (newname && strlen(newname)) named->SetName(newname);
101 return named;
102}
103
104// --------------------------------------------------------------------------
105//
106// Compare two MParContainer objects. Returns 0 when equal, -1 when this is
107// smaller and +1 when bigger (like strcmp).
108//
109Int_t MParContainer::Compare(const TObject *obj) const
110{
111 if (this == obj) return 0;
112 return fName.CompareTo(obj->GetName());
113}
114
115// --------------------------------------------------------------------------
116//
117// Copy this to obj.
118//
119void MParContainer::Copy(TObject &obj)
120{
121 MParContainer &cont = (MParContainer&)obj;
122
123 TObject::Copy(obj);
124
125 cont.fName = fName;
126 cont.fTitle = fTitle;
127
128 cont.fLog = fLog;
129 cont.fReadyToSave = fReadyToSave;
130}
131
132// --------------------------------------------------------------------------
133//
134// Encode MParContainer into output buffer.
135//
136void MParContainer::FillBuffer(char *&buffer)
137{
138 fName.FillBuffer(buffer);
139 fTitle.FillBuffer(buffer);
140}
141
142// --------------------------------------------------------------------------
143//
144// Return a unique name for this container. It is created from
145// the container name and the unique Id. (This is mostly used
146// in the StreamPrimitive member functions)
147//
148const TString MParContainer::GetUniqueName() const
149{
150 TString ret = ToLower(fName);
151
152 if (isdigit(ret[ret.Length()-1]))
153 ret+="_";
154
155 ret+=GetUniqueID();
156
157 return ret;
158}
159
160// --------------------------------------------------------------------------
161//
162// List MParContainer name and title.
163//
164void MParContainer::ls(Option_t *) const
165{
166 TROOT::IndentLevel();
167 *fLog << all << GetDescriptor() << " " << GetTitle() << ": kCanDelete=";
168 *fLog << Int_t(TestBit(kCanDelete)) << endl;
169}
170
171// --------------------------------------------------------------------------
172//
173// Print MParContainer name and title.
174//
175void MParContainer::Print(Option_t *) const
176{
177 *fLog << all << GetDescriptor() << " " << GetTitle() << endl;
178}
179
180// --------------------------------------------------------------------------
181//
182// Change (i.e. set) the name of the MParContainer.
183// WARNING !!
184// If the object is a member of a THashTable, THashList container
185// The HashTable must be Rehashed after SetName
186// For example the list of objects in the current directory is a THashList
187//
188void MParContainer::SetName(const char *name)
189{
190 fName = name;
191 ResetBit(kIsSavedAsPrimitive);
192 if (gPad && TestBit(kMustCleanup)) gPad->Modified();
193}
194
195// --------------------------------------------------------------------------
196//
197// Change (i.e. set) all the MParContainer parameters (name and title).
198// See also WARNING in SetName
199//
200void MParContainer::SetObject(const char *name, const char *title)
201{
202 fName = name;
203 fTitle = title;
204 ResetBit(kIsSavedAsPrimitive);
205 if (gPad && TestBit(kMustCleanup)) gPad->Modified();
206}
207
208// --------------------------------------------------------------------------
209//
210// Change (i.e. set) the title of the MParContainer.
211//
212void MParContainer::SetTitle(const char *title)
213{
214 fTitle = title;
215 ResetBit(kIsSavedAsPrimitive);
216 if (gPad && TestBit(kMustCleanup)) gPad->Modified();
217}
218
219// --------------------------------------------------------------------------
220//
221// Return size of the MParContainer part of the TObject.
222//
223Int_t MParContainer::Sizeof() const
224{
225 Int_t nbytes = fName.Sizeof() + fTitle.Sizeof();
226 return nbytes;
227}
228
229// --------------------------------------------------------------------------
230//
231// If you want to use Ascii-Input/-Output (eg. MWriteAsciiFile) of a
232// container, overload this function.
233//
234void MParContainer::AsciiRead(ifstream &fin)
235{
236 *fLog << warn << "To use the the ascii input of " << GetName();
237 *fLog << " you have to overload " << ClassName() << "::AsciiRead." << endl;
238}
239
240// --------------------------------------------------------------------------
241//
242// Write out a data member given as a TDataMember object to an output stream.
243//
244Bool_t MParContainer::WriteDataMember(ostream &out, const TDataMember *member, Double_t scale) const
245{
246 if (!member)
247 return kFALSE;
248
249 if (!member->IsPersistent() || member->Property()&kIsStatic)
250 return kFALSE;
251
252 /*const*/ TMethodCall *call = ((TDataMember*)member)->GetterMethod(); //FIXME: Root
253 if (!call)
254 {
255 *fLog << warn << "Sorry, no getter method found for " << member->GetName() << endl;
256 return kFALSE;
257 }
258
259 // For debugging: out << member->GetName() << ":";
260
261 switch (call->ReturnType())
262 {
263 case TMethodCall::kLong:
264 Long_t l;
265 call->Execute((void*)this, l); // FIXME: const, root
266 out << l << " ";
267 return kTRUE;
268
269 case TMethodCall::kDouble:
270 Double_t d;
271 call->Execute((void*)this, d); // FIXME: const, root
272 out << (scale*d) << " ";
273 return kTRUE;
274
275 default:
276 //case TMethodCall::kString:
277 //case TMethodCall::kOther:
278 /* someone may want to enhance this? */
279 return kFALSE;
280 }
281}
282
283// --------------------------------------------------------------------------
284//
285// Write out a data member given by name to an output stream.
286//
287Bool_t MParContainer::WriteDataMember(ostream &out, const char *member, Double_t scale) const
288{
289 /*const*/ TClass *cls = IsA()->GetBaseDataMember(member);
290 if (!cls)
291 return kFALSE;
292
293 return WriteDataMember(out, cls->GetDataMember(member), scale);
294}
295
296// --------------------------------------------------------------------------
297//
298// Write out a data member from a given TList of TDataMembers.
299// returns kTRUE when at least one member was successfully written
300//
301Bool_t MParContainer::WriteDataMember(ostream &out, const TList *list) const
302{
303 Bool_t rc = kFALSE;
304
305 TDataMember *data = NULL;
306
307 TIter Next(list);
308 while ((data=(TDataMember*)Next()))
309 rc |= WriteDataMember(out, data);
310
311 return rc;
312}
313
314// --------------------------------------------------------------------------
315//
316// If you want to use Ascii-Input/-Output (eg. MWriteAsciiFile) of a
317// container, you may overload this function. If you don't overload it
318// the data member of a class are written to the file in the order of
319// appearance in the class header (be more specfic: root dictionary)
320// Only data members which are of integer (Bool_t, Int_t, ...) or
321// floating point (Float_t, Double_t, ...) type are written.
322// returns kTRUE when at least one member was successfully written
323//
324Bool_t MParContainer::AsciiWrite(ostream &out) const
325{
326 // *fLog << warn << "To use the the ascii output of " << GetName();
327 // *fLog << " you have to overload " << ClassName() << "::AsciiWrite." << endl;
328
329 Bool_t rc = WriteDataMember(out, IsA()->GetListOfDataMembers());
330
331 TIter NextBaseClass(IsA()->GetListOfBases());
332 TBaseClass *base;
333 while ((base = (TBaseClass*) NextBaseClass()))
334 {
335 /*const*/ TClass *cls = base->GetClassPointer();
336
337 if (!cls)
338 continue;
339
340 if (cls->GetClassVersion())
341 rc |= WriteDataMember(out, cls->GetListOfDataMembers());
342 }
343
344 return rc;
345}
346
347TMethodCall *MParContainer::GetterMethod(const char *name) const
348{
349 TClass *cls = IsA()->GetBaseDataMember(name);
350 if (cls)
351 {
352 TDataMember *member = cls->GetDataMember(name);
353 if (!member)
354 {
355 *fLog << err << "Datamember '" << name << "' not in " << GetDescriptor() << endl;
356 return NULL;
357 }
358
359 TMethodCall *call = member->GetterMethod();
360 if (call)
361 return call;
362 }
363
364 *fLog << warn << "No standard access for '" << name << "' in ";
365 *fLog << GetDescriptor() << " or one of its base classes." << endl;
366
367 TMethodCall *call = NULL;
368
369 *fLog << warn << "Trying to find MethodCall '" << IsA()->GetName();
370 *fLog << "::Get" << name << "' instead <LEAKS MEMORY>" << endl;
371 call = new TMethodCall(IsA(), (TString)"Get"+name, "");
372 if (call->GetMethod())
373 return call;
374
375 delete call;
376
377 *fLog << warn << "Trying to find MethodCall '" << IsA()->GetName();
378 *fLog << "::" << name << "' instead <LEAKS MEMORY>" << endl;
379 call = new TMethodCall(IsA(), name, "");
380 if (call->GetMethod())
381 return call;
382
383 delete call;
384
385 *fLog << err << "Sorry, no getter method found for " << name << endl;
386 return NULL;
387}
388
389// --------------------------------------------------------------------------
390//
391// Implementation of SavePrimitive. Used to write the call to a constructor
392// to a macro. In the original root implementation it is used to write
393// gui elements to a macro-file.
394//
395void MParContainer::SavePrimitive(ofstream &out, Option_t *o)
396{
397 static UInt_t uid = 0;
398
399 if (IsSavedAsPrimitive())
400 return;
401
402 SetUniqueID(uid++);
403 SetBit(kIsSavedAsPrimitive);
404
405 if (gListOfPrimitives && !gListOfPrimitives->FindObject(this))
406 gListOfPrimitives->Add(this);
407
408 StreamPrimitive(out);
409}
410
411// --------------------------------------------------------------------------
412//
413// Creates the string written by SavePrimitive and returns it.
414//
415void MParContainer::StreamPrimitive(ofstream &out) const
416{
417 out << " // Using MParContainer::StreamPrimitive" << endl;
418 out << " " << ClassName() << " " << GetUniqueName() << "(\"";
419 out << fName << "\", \"" << fTitle << "\");" << endl;
420}
421
422void MParContainer::GetNames(TObjArray &arr) const
423{
424 arr.AddLast(new TNamed(fName, fTitle));
425}
426
427void MParContainer::SetNames(TObjArray &arr)
428{
429 TNamed *name = (TNamed*)arr.First();
430
431 fName = name->GetName();
432 fTitle = name->GetTitle();
433
434 delete arr.Remove(name);
435 arr.Compress();
436}
437
438// --------------------------------------------------------------------------
439//
440// Creates a new instance of this class. The idea is to create a clone of
441// this class in its initial state.
442//
443MParContainer *MParContainer::New() const
444{
445 return (MParContainer*)IsA()->New();
446}
Note: See TracBrowser for help on using the repository browser.