ATLAS Offline Software
Loading...
Searching...
No Matches
MetaObject.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7//
8// includes
9//
10
11//protect
13
14#include <cstdlib>
15#include <format>
16#include <memory>
17#include <sstream>
18#include <stdexcept>
19#include <TList.h>
20#include <TNamed.h>
21#include <TBuffer.h>
24
25//
26// method implementations
27//
28
30
31namespace SH
32{
33 namespace
34 {
35 template<class T> struct TypeName
36 {
37 static std::string name () {return typeid (T).name();}
38 };
39#define TYPENAME(X) \
40 template<> struct TypeName<X> { \
41 static std::string name () {return #X;}; };
42 TYPENAME (std::string)
43 TYPENAME (double)
44 TYPENAME (int)
45 TYPENAME (bool)
46#undef TYPENAME
47
48
49 template<class From,class To> struct Convert
50 {
51 static void convert (const std::string& /*from*/, To& /*to*/, const std::string& field)
52 {
53 if (field.empty())
54 return;
55 throw std::runtime_error ("no conversion defined from type " + TypeName<From>::name() + " to type " + TypeName<To>::name() + " for field " + field);
56 }
57 };
58
59 // the conversion string => type is a bit problematic, as it is
60 // expected to produce an exception if the conversion cannot be
61 // performed. this requires several lines of code. in order to avoid
62 // duplication, this has been made into an additional preprocessor
63 // macro. while a template function would have been nicer, this
64 // would not allow to add the target typename to the error message,
65 // which is why this approach has been chosen.
66 template<class To> struct Convert<std::string,To>
67 {
68 static void convert (const std::string& from, To& to, const std::string& field)
69 {
70 std::stringstream ss (from);
71 To retval;
72 ss >> retval;
73 if (!(ss.fail() || ss.rdbuf()->in_avail() > 0))
74 {
75 std::swap (retval, to);
76 return;
77 }
78 if (field.empty())
79 return;
80 throw std::runtime_error ("unable to convert string '" + from + "' to type " + TypeName<To>::name() + " for field " + field);
81 }
82 };
83
84 template<class Type> struct Convert<Type,Type>
85 {
86 static void convert (const Type& from, Type& to, const std::string& /*field*/)
87 {
88 to = from;
89 }
90 };
91
92 template<class From> struct Convert<From,std::string>
93 {
94 static void convert (const From& from, std::string& to, const std::string& /*field*/)
95 {
96 std::ostringstream ss;
97 ss << from;
98 to = ss.str();
99 }
100 };
101
102 template<> struct Convert<bool,std::string>
103 {
104 static void convert (const bool& from, std::string& to, const std::string& /*field*/)
105 {
106 if (from)
107 to = "true";
108 else
109 to = "false";
110 }
111 };
112
113 template<> struct Convert<std::string,bool>
114 {
115 static void convert (const std::string& from, bool& to, const std::string& field)
116 {
117 if (from == "true" || from == "True" || from == "TRUE" || from == "1")
118 {
119 to = true;
120 return;
121 }
122 if (from == "false" || from == "False" || from == "FALSE" || from == "0")
123 {
124 to = false;
125 return;
126 }
127 if (field.empty())
128 return;
129 throw std::runtime_error ("unable to convert string '" + from + "' to type bool for field " + field);
130 }
131 };
132
133#define DEFAULT_CONVERT(FROM,TO) \
134 template<> struct Convert<FROM,TO> { \
135 static void convert (const FROM& from, TO& to, const std::string& /*field*/) { \
136 to = from; } };
137 DEFAULT_CONVERT (std::string, std::string)
138 DEFAULT_CONVERT (bool, double)
139 DEFAULT_CONVERT (int, double)
140 DEFAULT_CONVERT (bool, int)
141 DEFAULT_CONVERT (double, int)
142 DEFAULT_CONVERT (int, bool)
143 DEFAULT_CONVERT (double, bool)
144#undef DEFAULT_CONVERT
145
146
147 template<class From,class To> bool
148 convertSingle (const TObject *from, To& to, const std::string& field)
149 {
150 const MetaData<From> *myfrom =
151 dynamic_cast<const MetaData<From>* >(from);
152 if (myfrom == 0)
153 return false;
154 Convert<From,To>::convert (myfrom->value, to, field);
155 return true;
156 }
157
158 template<class To> void
159 convert (const TObject *from, To& to, const std::string& field)
160 {
161 if (convertSingle<std::string> (from, to, field)) return;
162 if (convertSingle<double> (from, to, field)) return;
163 if (convertSingle<int> (from, to, field)) return;
164 if (convertSingle<bool> (from, to, field)) return;
165 if (!field.empty())
166 throw std::runtime_error (std::format ("unkown input type {} for field {}", typeid(*from).name(), field));
167 }
168
174 std::string trim (const std::string& str)
175 {
176 size_t endpos = str.find_last_not_of(" \t");
177 size_t startpos = str.find_first_not_of(" \t");
178 if( std::string::npos == endpos ) return "";
179 if(str[startpos] == '"' || str[startpos] == '\'') startpos++;
180 if(str[endpos] == '"' || str[endpos] == '\'') endpos--;
181 return str.substr( startpos, endpos+1-startpos );
182 }
183
184
185 /*
196 public:
197 template<class T> T getT(const std::string& name, T def_val) const;
198
208 public:
209 template<class T> static T convertT(const TObject* meta, T defval);
210 */
211 }
212
213
214
215 std::string dbg (const MetaObject& /*obj*/, unsigned /*verbosity*/)
216 {
217 return "MetaObject";
218 }
219
220
221
222 void swap (MetaObject& a, MetaObject& b)
223 {
224 a.swap (b);
225 }
226
227
228
229 void MetaObject ::
230 testInvariant () const
231 {
232 RCU_INVARIANT (m_dataList != 0);
233 }
234
235
236
237 MetaObject ::
238 MetaObject ()
239 : m_dataList (new TList)
240 {
241 m_dataList->SetOwner(true);
242 RCU_NEW_INVARIANT (this);
243 }
244
245
246
247 MetaObject ::
248 MetaObject (const MetaObject& that)
249 : TCollection (), m_dataList (new TList)
250 {
251 m_dataList->SetOwner(true);
252 TIter iter (&that);
253 TObject *object = 0;
254 while ((object = iter.Next()))
255 {
256 m_dataList->Add (object->Clone());
257 };
258
259 RCU_NEW_INVARIANT (this);
260 }
261
262
263
264 MetaObject ::
265 ~MetaObject ()
266 {
268
269 delete m_dataList;
270 }
271
272
273
274 MetaObject& MetaObject ::
275 operator = (const MetaObject& that)
276 {
277 // no invariant used
278 MetaObject tmp (that);
279 tmp.swap (*this);
280 return *this;
281 }
282
283
284
285 void MetaObject ::
286 swap (MetaObject& that)
287 {
288 std::swap (m_dataList, that.m_dataList);
289 }
290
291
292
293 void MetaObject ::
294 remove (const std::string& name)
295 {
297
298 TObject *object = 0;
299 while ((object = m_dataList->FindObject (name.c_str())))
300 delete m_dataList->Remove (object);
301 }
302
303
304
305 void MetaObject ::
306 addReplace (TNamed *meta_swallow)
307 {
308 std::unique_ptr<TNamed> meta (meta_swallow);
310 RCU_REQUIRE_SOFT (meta_swallow != 0);
311
312 remove (meta_swallow->GetName());
313 m_dataList->Add (meta.release());
314 }
315
316
317
318 TObject *MetaObject ::
319 get (const std::string& name)
320 {
321 RCU_READ_INVARIANT (this);
322 return m_dataList->FindObject (name.c_str());
323 }
324
325
326
327 const TObject *MetaObject ::
328 get (const std::string& name) const
329 {
330 RCU_READ_INVARIANT (this);
331 return m_dataList->FindObject (name.c_str());
332 }
333
334
335
336 double MetaObject ::
337 getDouble (const std::string& name, double def_val) const
338 {
339 // no invariant used
340 return castDouble (name, def_val, CAST_NOCAST_DEFAULT);
341 }
342
343
344
345 std::string MetaObject ::
346 getString (const std::string& name, const std::string& def_val) const
347 {
348 // no invariant used
349 return castString (name, def_val, CAST_NOCAST_DEFAULT);
350 }
351
352
353
354 double MetaObject ::
355 castDouble (const std::string& name, double def_val,
356 CastMode mode) const
357 {
358 return castT (name, def_val, mode);
359 }
360
361
362
363 std::string MetaObject ::
364 castString (const std::string& name, const std::string& def_val,
365 CastMode mode) const
366 {
367 return castT(name,def_val, mode);
368 }
369
370
371 int MetaObject ::
372 castInteger (const std::string& name, int def_val,
373 CastMode mode) const
374 {
375 return castT(name,def_val, mode);
376 }
377
378
379 bool MetaObject ::
380 castBool (const std::string& name, bool def_val,
381 CastMode mode) const
382 {
383 return castT(name,def_val, mode);
384 }
385
386
387 void MetaObject ::
388 setDouble (const std::string& name, double value)
389 {
390 setT (name, value);
391 }
392
393
394
395 void MetaObject ::
396 setString (const std::string& name, const std::string& value)
397 {
398 setT(name,value);
399 }
400
401
402 void MetaObject ::
403 setInteger (const std::string& name, int value)
404 {
405 setT(name,value);
406 }
407
408
409 void MetaObject ::
410 setBool (const std::string& name, bool value)
411 {
412 setT(name,value);
413 }
414
415
416 void MetaObject ::
417 fetch (const MetaObject& source)
418 {
420
421 TIter iter (&source);
422 TObject *object = 0;
423 while ((object = iter.Next()))
424 {
425 TNamed *const named = dynamic_cast<TNamed*>(object);
426 if (!named)
427 {
428 m_dataList->Add (object->Clone());
429 } else if (strncmp (named->GetName(), "nc_", 3) != 0)
430 {
431 addReplace (dynamic_cast<TNamed*>(named->Clone ()));
432 };
433 };
434 }
435
436
437
438 void MetaObject ::
439 fetchDefaults (const MetaObject& source)
440 {
442
443 TIter iter (&source);
444 TObject *object = 0;
445 while ((object = iter.Next()))
446 {
447 if (get (object->GetName ()) == 0)
448 m_dataList->Add (object->Clone());
449 };
450 }
451
452
453
454 void MetaObject ::
455 Add (TObject *meta_swallow)
456 {
457 std::unique_ptr<TObject> meta (meta_swallow);
459 RCU_REQUIRE_SOFT (meta_swallow != 0);
460 m_dataList->Add (meta.release());
461 }
462
463
464 void MetaObject ::
465 Add (TObject *meta_swallow, Option_t*)
466 {
467 this->Add (meta_swallow);
468 }
469
470
471
472 void MetaObject ::
473 Clear (Option_t *option)
474 {
476 m_dataList->Clear (option);
477 }
478
479
480
481 void MetaObject ::
482 Delete (Option_t *option)
483 {
485 m_dataList->Delete (option);
486 }
487
488
489
490 TObject **MetaObject ::
491 GetObjectRef (const TObject *const meta) const
492 {
493 RCU_READ_INVARIANT (this);
494 RCU_REQUIRE_SOFT (meta != 0);
495
496 TObject **const result = m_dataList->GetObjectRef (meta);
497
498 RCU_PROVIDE (result != 0);
499 RCU_PROVIDE (*result == meta);
500 return result;
501 }
502
503
504
505 TIterator *MetaObject ::
506 MakeIterator (Bool_t dir) const
507 {
508 RCU_READ_INVARIANT (this);
509
510 std::unique_ptr<TIterator> result (m_dataList->MakeIterator (dir));
511
512 RCU_PROVIDE2 (result.get() != 0, "result != 0");
513 return result.release();
514 }
515
516
517
518 TObject *MetaObject ::
519 Remove (TObject *meta)
520 {
522 RCU_REQUIRE_SOFT (meta != 0);
523 return m_dataList->Remove (meta);
524 }
525
526
527
528 void MetaObject ::
529 Streamer (TBuffer& b)
530 {
531 if (b.IsReading())
532 {
534 TObject::Streamer (b);
535 m_dataList->Clear ();
536 m_dataList->Streamer (b);
537 } else
538 {
539 RCU_READ_INVARIANT (this);
540 TObject::Streamer (b);
541 m_dataList->Streamer (b);
542 };
543 }
544
545
546 template<class T> T MetaObject ::
547 castT (const std::string& name, T def_val, CastMode mode) const
548 {
549 RCU_READ_INVARIANT (this);
550 const TObject* meta = get (name);
551 if (meta == 0)
552 return def_val;
553 const MetaData<T> *const retval = dynamic_cast<const MetaData<T>*>(meta);
554 if (retval)
555 return retval->value;
556 switch (mode)
557 {
558 case CAST_ERROR_THROW:
559 {
560 T result = def_val;
561 convert (meta, result, name);
562 return result;
563 }
564 case CAST_ERROR_DEFAULT:
565 {
566 T result = def_val;
567 convert (meta, result, "");
568 return result;
569 }
570 case CAST_NOCAST_THROW:
571 throw std::runtime_error ("invalid input value for " + name);
572 case CAST_NOCAST_DEFAULT:
573 return def_val;
574 }
575 RCU_ASSERT0 ("invalid cast value");
576 return def_val; //compiler dummy
577 }
578
579
580 void MetaObject ::
581 fetchFromString(const std::string& source){
582 size_t pos=1;
583 size_t oldpos = 0;
584 while(pos<source.size() && pos > 0){
585 size_t split = source.find("=",oldpos);
586 pos = source.find(",",split);
587 if(split < pos){
588 std::string key = trim(source.substr(oldpos,split-oldpos));
589 std::string value = trim(source.substr(split+1,pos-split-1));
590 this->setString(key,value);
591 } else {
592 throw std::runtime_error ("unable to parse string '" + source + "'");
593 }
594 oldpos = pos+1;
595 }
596 }
597
598 std::string MetaObject ::
599 dumpToString(){
600 std::stringstream ss;
601 TIterator* itr = this->MakeIterator();
602 TObject* obj = NULL;
603 while( (obj = itr->Next()) ){
604 Meta* m = dynamic_cast<Meta*>(obj);
605 if(!m) continue;
606 if(!ss.str().empty()) ss << ", ";
607 ss << m->GetName() << "=";
608 MetaData<std::string>* s = dynamic_cast<MetaData<std::string>* >(m);
609 if(s){
610 ss << "\"" << s->value << "\"";
611 } else {
612 std::string mystring;
613 convert<std::string> (m, mystring, m->GetName());
614 ss << mystring;
615 }
616 }
617 return ss.str();
618 }
619
620 Int_t MetaObject ::
621 GetEntries() const {
622 return this->m_dataList->GetEntries();
623 }
624
625}
#define RCU_INVARIANT(x)
Definition Assert.h:189
#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
static Double_t a
static Double_t ss
ClassImp(SH::MetaObject) namespace SH
#define DEFAULT_CONVERT(FROM, TO)
#define TYPENAME(X)
string trim(string s)
A class that manages meta-data to be associated with an object.
Definition MetaObject.h:48
void swap(MetaObject &a, MetaObject &b)
standard swap
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
This module provides a lot of global definitions, forward declarations and includes that are used by ...
Definition PrunDriver.h:15
-diff
STL namespace.
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)