/* ======================================================================== *\ ! ! * ! * This file is part of MARS, the MAGIC Analysis and Reconstruction ! * Software. It is distributed to you in the hope that it can be a useful ! * and timesaving tool in analysing Data of imaging Cerenkov telescopes. ! * It is distributed WITHOUT ANY WARRANTY. ! * ! * Permission to use, copy, modify and distribute this software and its ! * documentation for any purpose is hereby granted without fee, ! * provided that the above copyright notice appear in all copies and ! * that both that copyright notice and this permission notice appear ! * in supporting documentation. It is provided "as is" without express ! * or implied warranty. ! * ! ! ! Author(s): Thomas Bretz 12/2000 ! ! Copyright: MAGIC Software Development, 2000-2002 ! ! \* ======================================================================== */ ////////////////////////////////////////////////////////////////////////////// // // // MParContainer // // // // The MParContainer class is the base class for all MARS parameter // // containers. At the moment it is almost the same than ROOT's TNamed. // // A TNamed contains the essential elements (name, title) // // to identify a derived object in lists like our MParList or MTaskList. // // The main difference is that the name and title isn't stored and read // // to and from root files ("//!") // // // ////////////////////////////////////////////////////////////////////////////// #include "MParContainer.h" #include // isdigit #include // ofstream, AsciiWrite #include // TROOT::Identlevel #include // IsA #include // TObjArray #include // GetClassPointer #include // TMethodCall, AsciiWrite #include // TDataMember, AsciiWrite #include // gPad #include "MLog.h" #include "MLogManip.h" ClassImp(MParContainer); // -------------------------------------------------------------------------- // // MParContainer copy ctor // MParContainer::MParContainer(const MParContainer &named) { fName = named.fName; fTitle = named.fTitle; fLog = named.fLog; fReadyToSave = named.fReadyToSave; } // -------------------------------------------------------------------------- // // MParContainer assignment operator. // MParContainer& MParContainer::operator=(const MParContainer& rhs) { if (this == &rhs) return *this; TObject::operator=(rhs); fName = rhs.fName; fTitle = rhs.fTitle; fLog = rhs.fLog; fReadyToSave = rhs.fReadyToSave; return *this; } // -------------------------------------------------------------------------- // // Make a clone of an object using the Streamer facility. // If newname is specified, this will be the name of the new object // TObject *MParContainer::Clone(const char *newname) const { MParContainer *named = (MParContainer*)TObject::Clone(); if (newname && strlen(newname)) named->SetName(newname); return named; } // -------------------------------------------------------------------------- // // Compare two MParContainer objects. Returns 0 when equal, -1 when this is // smaller and +1 when bigger (like strcmp). // Int_t MParContainer::Compare(const TObject *obj) const { if (this == obj) return 0; return fName.CompareTo(obj->GetName()); } // -------------------------------------------------------------------------- // // Copy this to obj. // void MParContainer::Copy(TObject &obj) { MParContainer &cont = (MParContainer&)obj; TObject::Copy(obj); cont.fName = fName; cont.fTitle = fTitle; cont.fLog = fLog; cont.fReadyToSave = fReadyToSave; } // -------------------------------------------------------------------------- // // Encode MParContainer into output buffer. // void MParContainer::FillBuffer(char *&buffer) { fName.FillBuffer(buffer); fTitle.FillBuffer(buffer); } // -------------------------------------------------------------------------- // // Return a unique name for this container. It is created from // the container name and the unique Id. (This is mostly used // in the StreamPrimitive member functions) // const TString MParContainer::GetUniqueName() const { TString ret = ToLower(fName); if (isdigit(ret[ret.Length()-1])) ret+="_"; ret+=GetUniqueID(); return ret; } // -------------------------------------------------------------------------- // // List MParContainer name and title. // void MParContainer::ls(Option_t *) const { TROOT::IndentLevel(); *fLog << all << GetDescriptor() << " " << GetTitle() << ": kCanDelete="; *fLog << Int_t(TestBit(kCanDelete)) << endl; } // -------------------------------------------------------------------------- // // Print MParContainer name and title. // void MParContainer::Print(Option_t *) const { *fLog << all << GetDescriptor() << " " << GetTitle() << endl; } // -------------------------------------------------------------------------- // // Change (i.e. set) the name of the MParContainer. // WARNING !! // If the object is a member of a THashTable, THashList container // The HashTable must be Rehashed after SetName // For example the list of objects in the current directory is a THashList // void MParContainer::SetName(const char *name) { fName = name; ResetBit(kIsSavedAsPrimitive); if (gPad && TestBit(kMustCleanup)) gPad->Modified(); } // -------------------------------------------------------------------------- // // Change (i.e. set) all the MParContainer parameters (name and title). // See also WARNING in SetName // void MParContainer::SetObject(const char *name, const char *title) { fName = name; fTitle = title; ResetBit(kIsSavedAsPrimitive); if (gPad && TestBit(kMustCleanup)) gPad->Modified(); } // -------------------------------------------------------------------------- // // Change (i.e. set) the title of the MParContainer. // void MParContainer::SetTitle(const char *title) { fTitle = title; ResetBit(kIsSavedAsPrimitive); if (gPad && TestBit(kMustCleanup)) gPad->Modified(); } // -------------------------------------------------------------------------- // // Return size of the MParContainer part of the TObject. // Int_t MParContainer::Sizeof() const { Int_t nbytes = fName.Sizeof() + fTitle.Sizeof(); return nbytes; } // -------------------------------------------------------------------------- // // If you want to use Ascii-Input/-Output (eg. MWriteAsciiFile) of a // container, overload this function. // void MParContainer::AsciiRead(ifstream &fin) { *fLog << warn << "To use the the ascii input of " << GetName(); *fLog << " you have to overload " << ClassName() << "::AsciiRead." << endl; } // -------------------------------------------------------------------------- // // Write out a data member given as a TDataMember object to an output stream. // Bool_t MParContainer::WriteDataMember(ostream &out, const TDataMember *member, Double_t scale) const { if (!member) return kFALSE; if (!member->IsPersistent() || member->Property()&kIsStatic) return kFALSE; /*const*/ TMethodCall *call = ((TDataMember*)member)->GetterMethod(); //FIXME: Root if (!call) { *fLog << warn << "Sorry, no getter method found for " << member->GetName() << endl; return kFALSE; } // For debugging: out << member->GetName() << ":"; switch (call->ReturnType()) { case TMethodCall::kLong: Long_t l; call->Execute((void*)this, l); // FIXME: const, root out << l << " "; return kTRUE; case TMethodCall::kDouble: Double_t d; call->Execute((void*)this, d); // FIXME: const, root out << (scale*d) << " "; return kTRUE; default: //case TMethodCall::kString: //case TMethodCall::kOther: /* someone may want to enhance this? */ return kFALSE; } } // -------------------------------------------------------------------------- // // Write out a data member given by name to an output stream. // Bool_t MParContainer::WriteDataMember(ostream &out, const char *member, Double_t scale) const { /*const*/ TClass *cls = IsA()->GetBaseDataMember(member); if (!cls) return kFALSE; return WriteDataMember(out, cls->GetDataMember(member), scale); } // -------------------------------------------------------------------------- // // Write out a data member from a given TList of TDataMembers. // returns kTRUE when at least one member was successfully written // Bool_t MParContainer::WriteDataMember(ostream &out, const TList *list) const { Bool_t rc = kFALSE; TDataMember *data = NULL; TIter Next(list); while ((data=(TDataMember*)Next())) rc |= WriteDataMember(out, data); return rc; } // -------------------------------------------------------------------------- // // If you want to use Ascii-Input/-Output (eg. MWriteAsciiFile) of a // container, you may overload this function. If you don't overload it // the data member of a class are written to the file in the order of // appearance in the class header (be more specfic: root dictionary) // Only data members which are of integer (Bool_t, Int_t, ...) or // floating point (Float_t, Double_t, ...) type are written. // returns kTRUE when at least one member was successfully written // Bool_t MParContainer::AsciiWrite(ostream &out) const { // *fLog << warn << "To use the the ascii output of " << GetName(); // *fLog << " you have to overload " << ClassName() << "::AsciiWrite." << endl; Bool_t rc = WriteDataMember(out, IsA()->GetListOfDataMembers()); TIter NextBaseClass(IsA()->GetListOfBases()); TBaseClass *base; while ((base = (TBaseClass*) NextBaseClass())) { /*const*/ TClass *cls = base->GetClassPointer(); if (!cls) continue; if (cls->GetClassVersion()) rc |= WriteDataMember(out, cls->GetListOfDataMembers()); } return rc; } TMethodCall *MParContainer::GetterMethod(const char *name) const { TClass *cls = IsA()->GetBaseDataMember(name); if (!cls) { *fLog << err << "'" << name << "' is neither a member of "; *fLog << GetDescriptor() << " nor one of its base classes." << endl; return NULL; } TDataMember *member = cls->GetDataMember(name); if (!member) { *fLog << err << "Datamember '" << name << "' not in " << GetDescriptor() << endl; return NULL; } TMethodCall *call = member->GetterMethod(); if (!call) { *fLog << err << "Sorry, no getter method found for " << name << endl; return NULL; } return call; } // -------------------------------------------------------------------------- // // Implementation of SavePrimitive. Used to write the call to a constructor // to a macro. In the original root implementation it is used to write // gui elements to a macro-file. // void MParContainer::SavePrimitive(ofstream &out, Option_t *o) { static UInt_t uid = 0; if (IsSavedAsPrimitive()) return; SetUniqueID(uid++/*gRandom->Uniform(kMaxInt)*/); StreamPrimitive(out); SetBit(kIsSavedAsPrimitive); } // -------------------------------------------------------------------------- // // Creates the string written by SavePrimitive and returns it. // void MParContainer::StreamPrimitive(ofstream &out) const { out << " // Using MParContainer::StreamPrimitive" << endl; out << " " << ClassName() << " " << GetUniqueName() << "(\""; out << fName << "\", \"" << fTitle << "\");" << endl; } void MParContainer::GetNames(TObjArray &arr) const { arr.AddLast(new TNamed(fName, fTitle)); } void MParContainer::SetNames(TObjArray &arr) { TNamed *name = (TNamed*)arr.First(); fName = name->GetName(); fTitle = name->GetTitle(); delete arr.Remove(name); arr.Compress(); }