#ifndef ROOT_TMVA_Option
#define ROOT_TMVA_Option
#include <iomanip>
#include <sstream>
#include <vector>
#ifndef ROOT_TObject
#include "TObject.h"
#endif
#ifndef ROOT_TString
#include "TString.h"
#endif
#ifndef ROOT_TList
#include "TList.h"
#endif
#ifndef ROOT_TMVA_MsgLogger
#include "TMVA/MsgLogger.h"
#endif
namespace TMVA {
class Configurable;
class OptionBase : public TObject {
public:
friend class Configurable;
OptionBase( const TString& name, const TString& desc );
virtual ~OptionBase() {}
virtual const char* GetName() const { return fNameAllLower.Data(); }
virtual const char* TheName() const { return fName.Data(); }
virtual TString GetValue(Int_t i=-1) const = 0;
Bool_t IsSet() const { return fIsSet; }
virtual Bool_t IsArrayOpt() const = 0;
const TString& Description() const { return fDescription; }
virtual Bool_t IsPreDefinedVal(const TString&) const = 0;
virtual Bool_t HasPreDefinedVal() const = 0;
virtual Int_t GetArraySize() const = 0;
virtual Bool_t SetValue( const TString& vs, Int_t i=-1 );
using TObject::Print;
virtual void Print( std::ostream&, Int_t levelofdetail=0 ) const = 0;
private:
virtual void SetValueLocal(const TString& vs, Int_t i=-1) = 0;
const TString fName;
TString fNameAllLower;
const TString fDescription;
Bool_t fIsSet;
protected:
static MsgLogger& Log();
protected:
ClassDef(OptionBase,1);
};
template <class T>
class Option : public OptionBase {
public:
Option( T& ref, const TString& name, const TString& desc ) :
OptionBase(name, desc), fRefPtr(&ref) {}
virtual ~Option() {}
virtual TString GetValue( Int_t i=-1 ) const;
virtual const T& Value ( Int_t i=-1 ) const;
virtual Bool_t HasPreDefinedVal() const { return (fPreDefs.size()!=0); }
virtual Bool_t IsPreDefinedVal( const TString& ) const;
virtual Bool_t IsArrayOpt() const { return kFALSE; }
virtual Int_t GetArraySize() const { return 0; }
virtual void AddPreDefVal(const T&);
using OptionBase::Print;
virtual void Print ( std::ostream&, Int_t levelofdetail=0 ) const;
virtual void PrintPreDefs( std::ostream&, Int_t levelofdetail=0 ) const;
protected:
T& Value(Int_t=-1);
virtual void SetValueLocal( const TString& val, Int_t i=-1 );
virtual Bool_t IsPreDefinedValLocal( const T& ) const;
T* fRefPtr;
std::vector<T> fPreDefs;
};
template<typename T>
class Option<T*> : public Option<T> {
public:
Option( T*& ref, Int_t size, const TString& name, const TString& desc ) :
Option<T>(*ref,name, desc), fVRefPtr(&ref), fSize(size) {}
virtual ~Option() {}
TString GetValue( Int_t i ) const {
std::stringstream str;
str << std::scientific << Value(i);
return str.str();
}
const T& Value( Int_t i ) const { return (*fVRefPtr)[i]; }
virtual Bool_t IsArrayOpt() const { return kTRUE; }
virtual Int_t GetArraySize() const { return fSize; }
using Option<T>::Print;
virtual void Print( std::ostream&, Int_t levelofdetail=0 ) const;
virtual Bool_t SetValue( const TString& val, Int_t i=0 );
T& Value(Int_t i) { return (*fVRefPtr)[i]; }
T ** fVRefPtr;
Int_t fSize;
};
}
namespace TMVA {
template<class T>
inline const T& TMVA::Option<T>::Value( Int_t ) const {
return *fRefPtr;
}
template<class T>
inline T& TMVA::Option<T>::Value( Int_t ) {
return *fRefPtr;
}
template<class T>
inline TString TMVA::Option<T>::GetValue( Int_t ) const {
std::stringstream str;
str << std::scientific << this->Value();
return str.str();
}
template<>
inline TString TMVA::Option<Bool_t>::GetValue( Int_t ) const {
return Value() ? "True" : "False";
}
template<>
inline TString TMVA::Option<Bool_t*>::GetValue( Int_t i ) const {
return Value(i) ? "True" : "False";
}
template<class T>
inline Bool_t TMVA::Option<T>::IsPreDefinedVal( const TString& val ) const
{
T tmpVal;
std::stringstream str(val.Data());
str >> tmpVal;
return IsPreDefinedValLocal(tmpVal);
}
template<class T>
inline Bool_t TMVA::Option<T>::IsPreDefinedValLocal(const T& val) const
{
if (fPreDefs.size()==0) return kTRUE;
typename std::vector<T>::const_iterator predefIt;
predefIt = fPreDefs.begin();
for (;predefIt!=fPreDefs.end(); predefIt++)
if ( (*predefIt)==val ) return kTRUE;
return kFALSE;
}
template<>
inline Bool_t TMVA::Option<TString>::IsPreDefinedValLocal( const TString& val ) const
{
TString tVal(val);
tVal.ToLower();
if (fPreDefs.size()==0) return kFALSE;
Bool_t foundPreDef = kFALSE;
std::vector<TString>::const_iterator predefIt;
predefIt = fPreDefs.begin();
for (;predefIt!=fPreDefs.end(); predefIt++) {
TString s(*predefIt);
s.ToLower();
if (s==tVal) { foundPreDef = kTRUE; break; }
}
return foundPreDef;
}
template<class T>
inline void TMVA::Option<T>::AddPreDefVal( const T& val )
{
fPreDefs.push_back(val);
}
template<>
inline void TMVA::Option<Bool_t>::AddPreDefVal( const Bool_t& )
{
Log() << kFATAL << "<AddPreDefVal> predefined values for Option<Bool_t> don't make sense"
<< Endl;
}
template<>
inline void TMVA::Option<Float_t>::AddPreDefVal( const Float_t& )
{
Log() << kFATAL << "<AddPreDefVal> predefined values for Option<Float_t> don't make sense"
<< Endl;
}
template<class T>
inline void TMVA::Option<T>::Print( std::ostream& os, Int_t levelofdetail ) const
{
os << TheName() << ": " << "\"" << GetValue() << "\"" << " [" << Description() << "]";
this->PrintPreDefs(os,levelofdetail);
}
template<class T>
inline void TMVA::Option<T*>::Print( std::ostream& os, Int_t levelofdetail ) const
{
for (Int_t i=0; i<fSize; i++) {
if (i==0)
os << this->TheName() << "[" << i << "]: " << "\"" << this->GetValue(i) << "\"" << " [" << this->Description() << "]";
else
os << " " << this->TheName() << "[" << i << "]: " << "\"" << this->GetValue(i) << "\"";
if (i!=fSize-1) os << std::endl;
}
this->PrintPreDefs(os,levelofdetail);
}
template<class T>
inline void TMVA::Option<T>::PrintPreDefs( std::ostream& os, Int_t levelofdetail ) const
{
if (HasPreDefinedVal() && levelofdetail>0) {
os << std::endl << "PreDefined - possible values are:" << std::endl;
typename std::vector<T>::const_iterator predefIt;
predefIt = fPreDefs.begin();
for (;predefIt!=fPreDefs.end(); predefIt++) {
os << " ";
os << " - " << (*predefIt) << std::endl;
}
}
}
template<class T>
inline Bool_t TMVA::Option<T*>::SetValue( const TString& val, Int_t ind )
{
if (ind >= fSize) return kFALSE;
std::stringstream str(val.Data());
if (ind < 0) {
str >> Value(0);
for (Int_t i=1; i<fSize; i++) Value(i) = Value(0);
}
else {
str >> Value(ind);
}
return kTRUE;
}
template<class T>
inline void TMVA::Option<T>::SetValueLocal( const TString& val, Int_t i )
{
std::stringstream str(val.Data());
str >> Value(i);
}
template<>
inline void TMVA::Option<TString>::SetValueLocal( const TString& val, Int_t )
{
TString valToSet(val);
if (fPreDefs.size()!=0) {
TString tVal(val);
tVal.ToLower();
std::vector<TString>::const_iterator predefIt;
predefIt = fPreDefs.begin();
for (;predefIt!=fPreDefs.end(); predefIt++) {
TString s(*predefIt);
s.ToLower();
if (s==tVal) { valToSet = *predefIt; break; }
}
}
std::stringstream str(valToSet.Data());
str >> Value(-1);
}
template<>
inline void TMVA::Option<Bool_t>::SetValueLocal( const TString& val, Int_t )
{
TString valToSet(val);
valToSet.ToLower();
if (valToSet=="1" || valToSet=="true" || valToSet=="ktrue" || valToSet=="t") {
this->Value() = true;
}
else if (valToSet=="0" || valToSet=="false" || valToSet=="kfalse" || valToSet=="f") {
this->Value() = false;
}
else {
Log() << kFATAL << "<SetValueLocal> value \'" << val
<< "\' can not be interpreted as boolean" << Endl;
}
}
}
#endif