34 template<
class T>
struct TypeName
36 static std::string name () {
return typeid (T).name();}
39 template<> struct TypeName<X> { \
40 static std::string name () {return #X;}; };
48 template<
class From,
class To>
struct Convert
50 static void convert (
const std::string& , To& ,
const std::string& field)
54 throw std::runtime_error (
"no conversion defined from type " + TypeName<From>::name() +
" to type " + TypeName<To>::name() +
" for field " + field);
65 template<
class To>
struct Convert<
std::
string,To>
67 static void convert (
const std::string& from, To& to,
const std::string& field)
69 std::stringstream
ss (from);
72 if (!(
ss.fail() ||
ss.rdbuf()->in_avail() > 0))
79 throw std::runtime_error (
"unable to convert string '" + from +
"' to type " + TypeName<To>::name() +
" for field " + field);
83 template<
class Type>
struct Convert<
Type,
Type>
85 static void convert (
const Type& from,
Type& to,
const std::string& )
91 template<
class From>
struct Convert<From,
std::
string>
93 static void convert (
const From& from, std::string& to,
const std::string& )
95 std::ostringstream
ss;
101 template<>
struct Convert<bool,
std::
string>
103 static void convert (
const bool& from, std::string& to,
const std::string& )
112 template<>
struct Convert<
std::
string,bool>
114 static void convert (
const std::string& from,
bool& to,
const std::string& field)
116 if (from ==
"true" || from ==
"True" || from ==
"TRUE" || from ==
"1")
121 if (from ==
"false" || from ==
"False" || from ==
"FALSE" || from ==
"0")
128 throw std::runtime_error (
"unable to convert string '" + from +
"' to type bool for field " + field);
132#define DEFAULT_CONVERT(FROM,TO) \
133 template<> struct Convert<FROM,TO> { \
134 static void convert (const FROM& from, TO& to, const std::string& ) { \
143#undef DEFAULT_CONVERT
146 template<
class From,
class To>
bool
147 convertSingle (
const TObject *from, To& to,
const std::string& field)
149 const MetaData<From> *myfrom =
150 dynamic_cast<const MetaData<From>*
>(from);
151 if (myfrom ==
nullptr)
153 Convert<From,To>::convert (myfrom->value, to, field);
157 template<
class To>
void
158 convert (
const TObject *from, To& to,
const std::string& field)
160 if (convertSingle<std::string> (from, to, field))
return;
161 if (convertSingle<double> (from, to, field))
return;
162 if (convertSingle<int> (from, to, field))
return;
163 if (convertSingle<bool> (from, to, field))
return;
165 throw std::runtime_error (std::format (
"unknown input type {} for field {}",
typeid(*from).name(), field));
173 std::string
trim (
const std::string&
str)
175 const char *
const whitespace =
" \t\n\r\f\v";
176 size_t startpos =
str.find_first_not_of (whitespace);
177 if (std::string::npos == startpos)
return "";
178 size_t endpos =
str.find_last_not_of (whitespace);
181 if (endpos > startpos &&
182 (
str[startpos] ==
'"' ||
str[startpos] ==
'\'') &&
183 str[endpos] ==
str[startpos])
188 return str.substr (startpos, endpos + 1 - startpos);
204 template<class T> T getT(const std::string& name, T def_val) const;
216 template<class T> static T convertT(const TObject* meta, T defval);
222 std::string
dbg (
const MetaObject& ,
unsigned )
229 void swap (MetaObject&
a, MetaObject& b)
237 testInvariant ()
const
246 : m_dataList (
new TList)
248 m_dataList->SetOwner(
true);
255 MetaObject (
const MetaObject& that)
256 : TCollection (), m_dataList (
new TList)
258 m_dataList->SetOwner(
true);
260 TObject *
object =
nullptr;
261 while ((
object = iter.Next()))
263 m_dataList->Add (object->Clone());
281 MetaObject& MetaObject ::
282 operator = (
const MetaObject& that)
285 MetaObject tmp (that);
293 swap (MetaObject& that)
301 remove (
const std::string& name)
305 TObject *
object =
nullptr;
306 while ((
object = m_dataList->FindObject (name.c_str())))
307 delete m_dataList->Remove (
object);
313 addReplace (TNamed *meta_swallow)
315 std::unique_ptr<TNamed>
meta (meta_swallow);
319 remove (meta_swallow->GetName());
320 m_dataList->Add (
meta.release());
325 TObject *MetaObject ::
326 get (
const std::string& name)
329 return m_dataList->FindObject (name.c_str());
334 const TObject *MetaObject ::
335 get (
const std::string& name)
const
338 return m_dataList->FindObject (name.c_str());
344 getDouble (
const std::string& name,
double def_val)
const
347 return castDouble (name, def_val, CAST_NOCAST_DEFAULT);
352 std::string MetaObject ::
353 getString (
const std::string& name,
const std::string& def_val)
const
356 return castString (name, def_val, CAST_NOCAST_DEFAULT);
362 castDouble (
const std::string& name,
double def_val,
365 return castT (name, def_val, mode);
370 std::string MetaObject ::
371 castString (
const std::string& name,
const std::string& def_val,
374 return castT(name,def_val, mode);
379 castInteger (
const std::string& name,
int def_val,
382 return castT(name,def_val, mode);
387 castBool (
const std::string& name,
bool def_val,
390 return castT(name,def_val, mode);
395 setDouble (
const std::string& name,
double value)
403 setString (
const std::string& name,
const std::string& value)
410 setInteger (
const std::string& name,
int value)
417 setBool (
const std::string& name,
bool value)
424 fetch (
const MetaObject& source)
428 TIter iter (&source);
429 TObject *
object =
nullptr;
430 while ((
object = iter.Next()))
432 TNamed *
const named =
dynamic_cast<TNamed*
>(object);
435 m_dataList->Add (object->Clone());
436 }
else if (strncmp (named->GetName(),
"nc_", 3) != 0)
438 addReplace (
dynamic_cast<TNamed*
>(named->Clone ()));
446 fetchDefaults (
const MetaObject& source)
450 TIter iter (&source);
451 TObject *
object =
nullptr;
452 while ((
object = iter.Next()))
454 if (
get (object->GetName ()) ==
nullptr)
455 m_dataList->Add (object->Clone());
462 Add (TObject *meta_swallow)
464 std::unique_ptr<TObject>
meta (meta_swallow);
467 m_dataList->Add (
meta.release());
472 Add (TObject *meta_swallow, Option_t*)
474 this->Add (meta_swallow);
480 Clear (Option_t *option)
483 m_dataList->Clear (option);
489 Delete (Option_t *option)
492 m_dataList->Delete (option);
497 TObject **MetaObject ::
498 GetObjectRef (
const TObject *
const meta)
const
503 TObject **
const result = m_dataList->GetObjectRef (
meta);
512 TIterator *MetaObject ::
513 MakeIterator (Bool_t dir)
const
517 std::unique_ptr<TIterator> result (m_dataList->MakeIterator (dir));
520 return result.release();
525 TObject *MetaObject ::
526 Remove (TObject *
meta)
530 return m_dataList->Remove (
meta);
536 Streamer (TBuffer& b)
541 TObject::Streamer (b);
542 m_dataList->Clear ();
543 m_dataList->Streamer (b);
548 m_dataList->SetOwner (
true);
552 TObject::Streamer (b);
553 m_dataList->Streamer (b);
558 template<
class T> T MetaObject ::
559 castT (
const std::string& name, T def_val, CastMode mode)
const
562 const TObject*
meta =
get (name);
565 const MetaData<T> *
const retval =
dynamic_cast<const MetaData<T>*
>(
meta);
567 return retval->value;
570 case CAST_ERROR_THROW:
573 convert (
meta, result, name);
576 case CAST_ERROR_DEFAULT:
579 convert (
meta, result,
"");
582 case CAST_NOCAST_THROW:
583 throw std::runtime_error (
"invalid input value for " + name);
584 case CAST_NOCAST_DEFAULT:
593 fetchFromString(
const std::string& source){
595 while (oldpos < source.size())
597 size_t split = source.find (
"=", oldpos);
598 size_t pos = source.find (
",", oldpos);
599 if (pos == std::string::npos)
610 std::string key =
trim (source.substr (oldpos,
split - oldpos));
611 std::string value =
trim (source.substr (
split + 1, pos -
split - 1));
612 this->setString (key, value);
614 throw std::runtime_error (
"unable to parse string '" + source +
"'");
620 std::string MetaObject ::
621 dumpToString()
const {
622 std::stringstream
ss;
623 std::unique_ptr<TIterator> itr (this->MakeIterator());
624 TObject* obj =
nullptr;
625 while( (obj = itr->Next()) ){
626 Meta* m =
dynamic_cast<Meta*
>(obj);
628 if(!
ss.str().empty())
ss <<
", ";
629 ss << m->GetName() <<
"=";
630 MetaData<std::string>* s =
dynamic_cast<MetaData<std::string>*
>(m);
632 ss <<
"\"" << s->value <<
"\"";
634 std::string mystring;
635 convert<std::string> (m, mystring, m->GetName());
644 return this->m_dataList->GetEntries();
652 return this->m_dataList->GetSize();