ATLAS Offline Software
Loading...
Searching...
No Matches
MetaObject.cxx File Reference
#include <SampleHandler/MetaObject.h>
#include <cstdlib>
#include <format>
#include <memory>
#include <sstream>
#include <stdexcept>
#include <TList.h>
#include <TNamed.h>
#include <TBuffer.h>
#include <RootCoreUtils/Assert.h>
#include <SampleHandler/MetaData.h>

Go to the source code of this file.

Macros

#define TYPENAME(X)
#define DEFAULT_CONVERT(FROM, TO)

Functions

 ClassImp (SH::MetaObject) namespace SH

Macro Definition Documentation

◆ DEFAULT_CONVERT

#define DEFAULT_CONVERT ( FROM,
TO )
Value:
template<> struct Convert<FROM,TO> { \
static void convert (const FROM& from, TO& to, const std::string& /*field*/) { \
to = from; } };

◆ TYPENAME

#define TYPENAME ( X)
Value:
template<> struct TypeName<X> { \
static std::string name () {return #X;}; };

Function Documentation

◆ ClassImp()

ClassImp ( SH::MetaObject )
Author
Nils Krumnack

trim leading/trailing spaces from the given string

Guarantee
strong
Failures
out of memory II

Definition at line 28 of file MetaObject.cxx.

31{
32 namespace
33 {
34 template<class T> struct TypeName
35 {
36 static std::string name () {return typeid (T).name();}
37 };
38#define TYPENAME(X) \
39 template<> struct TypeName<X> { \
40 static std::string name () {return #X;}; };
41 TYPENAME (std::string)
42 TYPENAME (double)
43 TYPENAME (int)
44 TYPENAME (bool)
45#undef TYPENAME
46
47
48 template<class From,class To> struct Convert
49 {
50 static void convert (const std::string& /*from*/, To& /*to*/, const std::string& field)
51 {
52 if (field.empty())
53 return;
54 throw std::runtime_error ("no conversion defined from type " + TypeName<From>::name() + " to type " + TypeName<To>::name() + " for field " + field);
55 }
56 };
57
58 // the conversion string => type is a bit problematic, as it is
59 // expected to produce an exception if the conversion cannot be
60 // performed. this requires several lines of code. in order to avoid
61 // duplication, this has been made into an additional preprocessor
62 // macro. while a template function would have been nicer, this
63 // would not allow to add the target typename to the error message,
64 // which is why this approach has been chosen.
65 template<class To> struct Convert<std::string,To>
66 {
67 static void convert (const std::string& from, To& to, const std::string& field)
68 {
69 std::stringstream ss (from);
70 To retval;
71 ss >> retval;
72 if (!(ss.fail() || ss.rdbuf()->in_avail() > 0))
73 {
74 std::swap (retval, to);
75 return;
76 }
77 if (field.empty())
78 return;
79 throw std::runtime_error ("unable to convert string '" + from + "' to type " + TypeName<To>::name() + " for field " + field);
80 }
81 };
82
83 template<class Type> struct Convert<Type,Type>
84 {
85 static void convert (const Type& from, Type& to, const std::string& /*field*/)
86 {
87 to = from;
88 }
89 };
90
91 template<class From> struct Convert<From,std::string>
92 {
93 static void convert (const From& from, std::string& to, const std::string& /*field*/)
94 {
95 std::ostringstream ss;
96 ss << from;
97 to = ss.str();
98 }
99 };
100
101 template<> struct Convert<bool,std::string>
102 {
103 static void convert (const bool& from, std::string& to, const std::string& /*field*/)
104 {
105 if (from)
106 to = "true";
107 else
108 to = "false";
109 }
110 };
111
112 template<> struct Convert<std::string,bool>
113 {
114 static void convert (const std::string& from, bool& to, const std::string& field)
115 {
116 if (from == "true" || from == "True" || from == "TRUE" || from == "1")
117 {
118 to = true;
119 return;
120 }
121 if (from == "false" || from == "False" || from == "FALSE" || from == "0")
122 {
123 to = false;
124 return;
125 }
126 if (field.empty())
127 return;
128 throw std::runtime_error ("unable to convert string '" + from + "' to type bool for field " + field);
129 }
130 };
131
132#define DEFAULT_CONVERT(FROM,TO) \
133 template<> struct Convert<FROM,TO> { \
134 static void convert (const FROM& from, TO& to, const std::string& /*field*/) { \
135 to = from; } };
136 DEFAULT_CONVERT (std::string, std::string)
137 DEFAULT_CONVERT (bool, double)
138 DEFAULT_CONVERT (int, double)
139 DEFAULT_CONVERT (bool, int)
140 DEFAULT_CONVERT (double, int)
141 DEFAULT_CONVERT (int, bool)
142 DEFAULT_CONVERT (double, bool)
143#undef DEFAULT_CONVERT
144
145
146 template<class From,class To> bool
147 convertSingle (const TObject *from, To& to, const std::string& field)
148 {
149 const MetaData<From> *myfrom =
150 dynamic_cast<const MetaData<From>* >(from);
151 if (myfrom == nullptr)
152 return false;
153 Convert<From,To>::convert (myfrom->value, to, field);
154 return true;
155 }
156
157 template<class To> void
158 convert (const TObject *from, To& to, const std::string& field)
159 {
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;
164 if (!field.empty())
165 throw std::runtime_error (std::format ("unknown input type {} for field {}", typeid(*from).name(), field));
166 }
167
173 std::string trim (const std::string& str)
174 {
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);
179 // rationale: only strip a surrounding pair of *matching* quotes,
180 // not a mismatched pair like '"abc' or "abc'.
181 if (endpos > startpos &&
182 (str[startpos] == '"' || str[startpos] == '\'') &&
183 str[endpos] == str[startpos])
184 {
185 ++ startpos;
186 -- endpos;
187 }
188 return str.substr (startpos, endpos + 1 - startpos);
189 }
190
191
192 /*
203 public:
204 template<class T> T getT(const std::string& name, T def_val) const;
205
215 public:
216 template<class T> static T convertT(const TObject* meta, T defval);
217 */
218 }
219
220
221
222 std::string dbg (const MetaObject& /*obj*/, unsigned /*verbosity*/)
223 {
224 return "MetaObject";
225 }
226
227
228
229 void swap (MetaObject& a, MetaObject& b)
230 {
231 a.swap (b);
232 }
233
234
235
236 void MetaObject ::
237 testInvariant () const
238 {
239 RCU_INVARIANT (m_dataList != nullptr);
240 }
241
242
243
244 MetaObject ::
245 MetaObject ()
246 : m_dataList (new TList)
247 {
248 m_dataList->SetOwner(true);
249 RCU_NEW_INVARIANT (this);
250 }
251
252
253
254 MetaObject ::
255 MetaObject (const MetaObject& that)
256 : TCollection (), m_dataList (new TList)
257 {
258 m_dataList->SetOwner(true);
259 TIter iter (&that);
260 TObject *object = nullptr;
261 while ((object = iter.Next()))
262 {
263 m_dataList->Add (object->Clone());
264 }
265
266 RCU_NEW_INVARIANT (this);
267 }
268
269
270
271 MetaObject ::
272 ~MetaObject ()
273 {
275
276 delete m_dataList;
277 }
278
279
280
281 MetaObject& MetaObject ::
282 operator = (const MetaObject& that)
283 {
284 // no invariant used
285 MetaObject tmp (that);
286 tmp.swap (*this);
287 return *this;
288 }
289
290
291
292 void MetaObject ::
293 swap (MetaObject& that)
294 {
295 std::swap (m_dataList, that.m_dataList);
296 }
297
298
299
300 void MetaObject ::
301 remove (const std::string& name)
302 {
304
305 TObject *object = nullptr;
306 while ((object = m_dataList->FindObject (name.c_str())))
307 delete m_dataList->Remove (object);
308 }
309
310
311
312 void MetaObject ::
313 addReplace (TNamed *meta_swallow)
314 {
315 std::unique_ptr<TNamed> meta (meta_swallow);
317 RCU_REQUIRE_SOFT (meta_swallow != nullptr);
318
319 remove (meta_swallow->GetName());
320 m_dataList->Add (meta.release());
321 }
322
323
324
325 TObject *MetaObject ::
326 get (const std::string& name)
327 {
328 RCU_READ_INVARIANT (this);
329 return m_dataList->FindObject (name.c_str());
330 }
331
332
333
334 const TObject *MetaObject ::
335 get (const std::string& name) const
336 {
337 RCU_READ_INVARIANT (this);
338 return m_dataList->FindObject (name.c_str());
339 }
340
341
342
343 double MetaObject ::
344 getDouble (const std::string& name, double def_val) const
345 {
346 // no invariant used
347 return castDouble (name, def_val, CAST_NOCAST_DEFAULT);
348 }
349
350
351
352 std::string MetaObject ::
353 getString (const std::string& name, const std::string& def_val) const
354 {
355 // no invariant used
356 return castString (name, def_val, CAST_NOCAST_DEFAULT);
357 }
358
359
360
361 double MetaObject ::
362 castDouble (const std::string& name, double def_val,
363 CastMode mode) const
364 {
365 return castT (name, def_val, mode);
366 }
367
368
369
370 std::string MetaObject ::
371 castString (const std::string& name, const std::string& def_val,
372 CastMode mode) const
373 {
374 return castT(name,def_val, mode);
375 }
376
377
378 int MetaObject ::
379 castInteger (const std::string& name, int def_val,
380 CastMode mode) const
381 {
382 return castT(name,def_val, mode);
383 }
384
385
386 bool MetaObject ::
387 castBool (const std::string& name, bool def_val,
388 CastMode mode) const
389 {
390 return castT(name,def_val, mode);
391 }
392
393
394 void MetaObject ::
395 setDouble (const std::string& name, double value)
396 {
397 setT (name, value);
398 }
399
400
401
402 void MetaObject ::
403 setString (const std::string& name, const std::string& value)
404 {
405 setT(name,value);
406 }
407
408
409 void MetaObject ::
410 setInteger (const std::string& name, int value)
411 {
412 setT(name,value);
413 }
414
415
416 void MetaObject ::
417 setBool (const std::string& name, bool value)
418 {
419 setT(name,value);
420 }
421
422
423 void MetaObject ::
424 fetch (const MetaObject& source)
425 {
427
428 TIter iter (&source);
429 TObject *object = nullptr;
430 while ((object = iter.Next()))
431 {
432 TNamed *const named = dynamic_cast<TNamed*>(object);
433 if (!named)
434 {
435 m_dataList->Add (object->Clone());
436 } else if (strncmp (named->GetName(), "nc_", 3) != 0)
437 {
438 addReplace (dynamic_cast<TNamed*>(named->Clone ()));
439 }
440 }
441 }
442
443
444
445 void MetaObject ::
446 fetchDefaults (const MetaObject& source)
447 {
449
450 TIter iter (&source);
451 TObject *object = nullptr;
452 while ((object = iter.Next()))
453 {
454 if (get (object->GetName ()) == nullptr)
455 m_dataList->Add (object->Clone());
456 }
457 }
458
459
460
461 void MetaObject ::
462 Add (TObject *meta_swallow)
463 {
464 std::unique_ptr<TObject> meta (meta_swallow);
466 RCU_REQUIRE_SOFT (meta_swallow != nullptr);
467 m_dataList->Add (meta.release());
468 }
469
470
471 void MetaObject ::
472 Add (TObject *meta_swallow, Option_t*)
473 {
474 this->Add (meta_swallow);
475 }
476
477
478
479 void MetaObject ::
480 Clear (Option_t *option)
481 {
483 m_dataList->Clear (option);
484 }
485
486
487
488 void MetaObject ::
489 Delete (Option_t *option)
490 {
492 m_dataList->Delete (option);
493 }
494
495
496
497 TObject **MetaObject ::
498 GetObjectRef (const TObject *const meta) const
499 {
500 RCU_READ_INVARIANT (this);
501 RCU_REQUIRE_SOFT (meta != nullptr);
502
503 TObject **const result = m_dataList->GetObjectRef (meta);
504
505 RCU_PROVIDE (result != nullptr);
506 RCU_PROVIDE (*result == meta);
507 return result;
508 }
509
510
511
512 TIterator *MetaObject ::
513 MakeIterator (Bool_t dir) const
514 {
515 RCU_READ_INVARIANT (this);
516
517 std::unique_ptr<TIterator> result (m_dataList->MakeIterator (dir));
518
519 RCU_PROVIDE2 (result.get() != nullptr, "result != 0");
520 return result.release();
521 }
522
523
524
525 TObject *MetaObject ::
526 Remove (TObject *meta)
527 {
529 RCU_REQUIRE_SOFT (meta != nullptr);
530 return m_dataList->Remove (meta);
531 }
532
533
534
535 void MetaObject ::
536 Streamer (TBuffer& b)
537 {
538 if (b.IsReading())
539 {
541 TObject::Streamer (b);
542 m_dataList->Clear ();
543 m_dataList->Streamer (b);
544 // rationale: re-assert ownership of the list after reading, so
545 // that objects written by builds predating the SetOwner(true)
546 // calls do not read back as a non-owning list that leaks every
547 // Meta on destruction.
548 m_dataList->SetOwner (true);
549 } else
550 {
551 RCU_READ_INVARIANT (this);
552 TObject::Streamer (b);
553 m_dataList->Streamer (b);
554 }
555 }
556
557
558 template<class T> T MetaObject ::
559 castT (const std::string& name, T def_val, CastMode mode) const
560 {
561 RCU_READ_INVARIANT (this);
562 const TObject* meta = get (name);
563 if (meta == nullptr)
564 return def_val;
565 const MetaData<T> *const retval = dynamic_cast<const MetaData<T>*>(meta);
566 if (retval)
567 return retval->value;
568 switch (mode)
569 {
570 case CAST_ERROR_THROW:
571 {
572 T result = def_val;
573 convert (meta, result, name);
574 return result;
575 }
576 case CAST_ERROR_DEFAULT:
577 {
578 T result = def_val;
579 convert (meta, result, "");
580 return result;
581 }
582 case CAST_NOCAST_THROW:
583 throw std::runtime_error ("invalid input value for " + name);
584 case CAST_NOCAST_DEFAULT:
585 return def_val;
586 }
587 RCU_ASSERT0 ("invalid cast value");
588 return def_val; //compiler dummy
589 }
590
591
592 void MetaObject ::
593 fetchFromString(const std::string& source){
594 size_t oldpos = 0;
595 while (oldpos < source.size())
596 {
597 size_t split = source.find ("=", oldpos);
598 size_t pos = source.find (",", oldpos);
599 if (pos == std::string::npos)
600 pos = source.size();
601 // rationale: tolerate empty segments and a trailing separator
602 // (e.g. "a=b,") by skipping empty segments.
603 if (pos == oldpos)
604 {
605 oldpos = pos + 1;
606 continue;
607 }
608 if (split < pos)
609 {
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);
613 } else {
614 throw std::runtime_error ("unable to parse string '" + source + "'");
615 }
616 oldpos = pos + 1;
617 }
618 }
619
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);
627 if(!m) continue;
628 if(!ss.str().empty()) ss << ", ";
629 ss << m->GetName() << "=";
630 MetaData<std::string>* s = dynamic_cast<MetaData<std::string>* >(m);
631 if(s){
632 ss << "\"" << s->value << "\"";
633 } else {
634 std::string mystring;
635 convert<std::string> (m, mystring, m->GetName());
636 ss << mystring;
637 }
638 }
639 return ss.str();
640 }
641
642 Int_t MetaObject ::
643 GetEntries() const {
644 return this->m_dataList->GetEntries();
645 }
646
647 Int_t MetaObject ::
648 GetSize() const {
649 // rationale: TCollection::GetSize() is not overridden by
650 // GetEntries(), and fSize is never maintained, so the default
651 // returns 0 (e.g. PyROOT's len()); delegate to the backing list.
652 return this->m_dataList->GetSize();
653 }
654
655}
#define RCU_INVARIANT(x)
Definition Assert.h:187
#define RCU_PROVIDE2(x, y)
Definition Assert.h:205
#define RCU_DESTROY_INVARIANT(x)
Definition Assert.h:223
#define RCU_CHANGE_INVARIANT(x)
Definition Assert.h:219
#define RCU_NEW_INVARIANT(x)
Definition Assert.h:221
#define RCU_PROVIDE(x)
Definition Assert.h:203
#define RCU_REQUIRE_SOFT(x)
Definition Assert.h:141
#define RCU_ASSERT0(y)
Definition Assert.h:214
#define RCU_READ_INVARIANT(x)
Definition Assert.h:217
void swap(DataVector< T > &a, DataVector< T > &b)
See DataVector<T, BASE>::swap().
static Double_t a
static Double_t ss
#define DEFAULT_CONVERT(FROM, TO)
#define TYPENAME(X)
string trim(string s)
RootType Type
STL class.
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:132
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:179
CONT to(RANGE &&r)
Definition ranges.h:39
std::unique_ptr< MVAUtils::BDT > convert(TMVA::MethodBDT *bdt, bool isRegression=true, bool useYesNoLeaf=false)
unsigned long long T
-diff
STL namespace.
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)
setBGCode setTAP setLVL2ErrorBits bool