ATLAS Offline Software
Loading...
Searching...
No Matches
ObjectMetadata.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5// Local include(s):
7
8// Boost include(s):
9#include <boost/tokenizer.hpp>
10
11// Gaudi/Athena include(s):
12#include "GaudiKernel/System.h"
14
15
16
18namespace {
19
21
31 bool isPrimitive( const std::type_info& ti ) {
32
33 if( ( ti == typeid( char* ) ) ||
34 ( ti == typeid( char ) ) ||
35 ( ti == typeid( unsigned char ) ) ||
36 ( ti == typeid( short ) ) ||
37 ( ti == typeid( unsigned short ) ) ||
38 ( ti == typeid( int ) ) ||
39 ( ti == typeid( unsigned int ) ) ||
40 ( ti == typeid( float ) ) ||
41 ( ti == typeid( double ) ) ||
42 ( ti == typeid( long long ) ) ||
43 ( ti == typeid( unsigned long long ) ) ||
44 ( ti == typeid( bool ) ) ) {
45
46 return true;
47 }
48
49 return false;
50 }
51
52} // namespace
53
54namespace D3PD {
55
56 // Set the value of the constant(s):
58 const char* const ObjectMetadata::STRING_SEPARATOR = "@";
59 const unsigned int ObjectMetadata::SERIALIZER_VERSION = 1;
60 const char* const ObjectMetadata::Variable::STRING_SEPARATOR = "$";
61
63 : m_variables(), m_name( "" ), m_prefix( "" ),
64 m_container( false ) {
65
66 }
67
69 : m_variables( parent.m_variables ), m_name( parent.m_name ),
70 m_prefix( parent.m_prefix ), m_container( parent.m_container ) {
71
72 }
73
75 {
76 if (&parent != this) {
77 m_variables = parent.m_variables;
78 m_name = parent.m_name;
79 m_prefix = parent.m_prefix;
80 m_container = parent.m_container;
81 }
82
83 return *this;
84 }
85
87
88 return ( ( name() == rhs.name() ) && ( prefix() == rhs.prefix() ) &&
89 ( container() == rhs.container() ) );
90 }
91
92 bool ObjectMetadata::operator< ( const ObjectMetadata& rhs ) const {
93
94 if( prefix() != rhs.prefix() ) {
95 return ( prefix() < rhs.prefix() );
96 } else if( name() != rhs.name() ) {
97 return ( name() < rhs.name() );
98 } else {
99 return ( container() < rhs.container() );
100 }
101 }
102
110 StatusCode ObjectMetadata::addVariable( const std::string& name,
111 const std::type_info& ti,
112 void*& /*ptr*/,
113 std::string_view docstring,
114 const void* /*defval*/ ) {
115
116 // Check that the variable has the correct prefix:
117 if( m_prefix != "" &&
118 !name.starts_with( m_prefix) )
119 {
120 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR, "ObjectMetadata" )
121 << "Specified variable name (" << name << ") doesn't have the "
122 << "expected prefix (" << m_prefix << ")";
123 return StatusCode::RECOVERABLE;
124 }
125
126 // Create a new variable:
127 Variable var;
128
129 // Remove the prefix from the variable name:
130 var.setName( name.substr( m_prefix.size(), name.npos ) );
131
132 // Check if it's already amongst the existing variables:
133 if( m_variables.find( var ) != m_variables.end() ) {
134 return StatusCode::SUCCESS;
135 }
136
137 // Set the type of the variable:
138 var.setType( System::typeinfoName( ti.name() ) );
139
140 // Set whether the variable is a primitive:
141 var.setPrimitive( isPrimitive( ti ) );
142
143 // Set the documentation string for the variable:
144 var.setDoc( docstring );
145
146 // Remember the variable:
147 m_variables.insert( std::move(var) );
148
149 return StatusCode::SUCCESS;
150 }
151
157 StatusCode
158 ObjectMetadata::addDimensionedVariable( const std::string& /*name*/,
159 const std::type_info& /*ti*/,
160 void*& /*ptr*/,
161 const std::string& /*dim*/,
162 std::string_view /*docstring*/,
163 const void* /*defval*/ ) {
164
165 REPORT_MESSAGE_WITH_CONTEXT( MSG::FATAL, "ObjectMetadata" )
166 << "addDimensionedVariable(...) not implemented";
167
168 return StatusCode::FAILURE;
169 }
170
171 const std::string& ObjectMetadata::name() const {
172
173 return m_name;
174 }
175
176 void ObjectMetadata::setName( const std::string& name ) {
177
178 m_name = name;
179 return;
180 }
181
192 std::string ObjectMetadata::metadataName ATLAS_NOT_THREAD_SAFE () const {
193
194 // Variable used to give names to unnamed D3PDObject-s
195 static size_t objectCounter = 0;
196 std::string name = m_name;
197 if (name.empty()) {
198 ++objectCounter;
199 name = "D3PDObject" + std::to_string( objectCounter );
200 }
201 return name + "_" + genSuffix (name, RANDOM_NAME_POSTFIX_LENGTH);
202 }
203
214 std::string ObjectMetadata::objectName( const std::string& metaName ) {
215
216 return metaName.substr( 0, metaName.size() -
218 }
219
220 const std::string& ObjectMetadata::prefix() const {
221
222 return m_prefix;
223 }
224
225 void ObjectMetadata::setPrefix( const std::string& prefix ) {
226
228 return;
229 }
230
232
233 return m_container;
234 }
235
237
239 return;
240 }
241
250 std::string ObjectMetadata::toString() const {
251
252 // Save the simple part of the information
253 std::string result =
254 std::to_string( SERIALIZER_VERSION ) +
256 STRING_SEPARATOR + ( m_container ? "1" : "0" );
257
258 // Save the serialized version of all the variables:
259 std::set< Variable >::const_iterator itr = m_variables.begin();
260 std::set< Variable >::const_iterator end = m_variables.end();
261 for( ; itr != end; ++itr ) {
262 result += STRING_SEPARATOR + itr->toString();
263 }
264
265 return result;
266 }
267
277 StatusCode ObjectMetadata::read( const std::string& data ) {
278
279 //
280 // Tokenize the string using Boost:
281 //
282 boost::char_separator< char > separator( STRING_SEPARATOR, "",
283 boost::keep_empty_tokens );
284 boost::tokenizer< boost::char_separator< char > > tokens( data,
285 separator );
286 boost::tokenizer< boost::char_separator< char > >::const_iterator itr = tokens.begin();
287 boost::tokenizer< boost::char_separator< char > >::const_iterator end = tokens.end();
288
289 // Check that we didn't reach the last token yet:
290 if( itr == end ) {
291 REPORT_MESSAGE_WITH_CONTEXT( MSG::FATAL, "ObjectMetadata" )
292 << "The received data can not be parsed successfully: "
293 << data;
294 return StatusCode::FAILURE;
295 }
296
297 // Check that the metadata was saved using the same version of the
298 // serializer code. Later on we might want to introduce backward
299 // compatibility, but for now this simple check should be enough.
300 if( atoi(itr->c_str()) != SERIALIZER_VERSION ) {
301 REPORT_MESSAGE_WITH_CONTEXT( MSG::FATAL, "ObjectMetadata" )
302 << "Version mismatch! The metadata was saved with a different "
303 << "serialization version (" << *itr << ") than the code used ("
304 << SERIALIZER_VERSION << ")";
305 return StatusCode::FAILURE;
306 }
307
308 ++itr;
309
310 // Check that we didn't reach the last token yet:
311 if( itr == end ) {
312 REPORT_MESSAGE_WITH_CONTEXT( MSG::FATAL, "ObjectMetadata" )
313 << "The received data can not be parsed successfully: "
314 << data;
315 return StatusCode::FAILURE;
316 }
317
318 // Extract the prefix from the metadata:
319 m_prefix = *itr; ++itr;
320
321 // Check that we didn't reach the last token yet:
322 if( itr == end ) {
323 REPORT_MESSAGE_WITH_CONTEXT( MSG::FATAL, "ObjectMetadata" )
324 << "The received data can not be parsed successfully: "
325 << data;
326 return StatusCode::FAILURE;
327 }
328
329 // Extract whether this is a container that the variables describe:
330 if( *itr == "0" ) {
331 m_container = false;
332 } else if( *itr == "1" ) {
333 m_container = true;
334 } else {
335 REPORT_MESSAGE_WITH_CONTEXT( MSG::FATAL, "ObjectMetadata" )
336 << "The received data can not be parsed successfully: "
337 << data;
338 return StatusCode::FAILURE;
339 }
340
341 ++itr;
342
343 // Finally, let's extract all the variable metadata:
344 for( ; itr != end; ++itr ) {
345 Variable var;
346 CHECK( var.read( *itr ) );
347 m_variables.insert( std::move(var) );
348 }
349
350 return StatusCode::SUCCESS;
351 }
352
354
355 // Clear/reset all the variables:
356 m_variables.clear();
357 m_name = "";
358 m_prefix = "";
359 m_container = false;
360
361 return;
362 }
363
365
366 return this->merge( obj );
367 }
368
377
378 // Only objects with the same "name" should be merged:
379 if( name() != obj.name() ) {
380 REPORT_MESSAGE_WITH_CONTEXT( MSG::WARNING, "ObjectMetadata" )
381 << "Can't merge object with name \"" << obj.name()
382 << "\" into another object with name \"" << name() << "\"";
383 return *this;
384 }
385
386 // Now merge all the variable definitions:
387 std::set< Variable >::const_iterator itr = obj.variables().begin();
388 std::set< Variable >::const_iterator end = obj.variables().end();
389 for( ; itr != end; ++itr ) {
390 m_variables.insert( *itr );
391 }
392
393 return *this;
394 }
395
407 std::string ObjectMetadata::genSuffix ATLAS_NOT_THREAD_SAFE (const std::string& name,
408 size_t length)
409 {
410
411 // Count of the number of times a given name was used,
412 // in order to assign them a unique suffix.
413 static std::unordered_map<std::string, size_t> namecount;
414
415 const size_t count = ++namecount[name];
416 std::ostringstream os;
417 os << std::setw(length) << std::setprecision(length) << std::setfill('0')
418 << count;
419 return os.str();
420 }
421
422
424 : m_type( "" ), m_name( "" ), m_doc( "" ), m_primitive( true ) {
425
426 }
427
428 const std::string& ObjectMetadata::Variable::type() const {
429
430 return m_type;
431 }
432
433 const std::string& ObjectMetadata::Variable::name() const {
434
435 return m_name;
436 }
437
438 const std::string& ObjectMetadata::Variable::doc() const {
439
440 return m_doc;
441 }
442
444
445 return m_primitive;
446 }
447
448 void ObjectMetadata::Variable::setType( const std::string& type ) {
449
450 m_type = type;
451 return;
452 }
453
454 void ObjectMetadata::Variable::setName( const std::string& name ) {
455
456 m_name = name;
457 return;
458 }
459
460 void ObjectMetadata::Variable::setDoc( std::string_view doc ) {
461
462 m_doc.assign(doc);
463 return;
464 }
465
467
469 return;
470 }
471
481
483 m_doc + STRING_SEPARATOR + ( m_primitive ? "1" : "0" );
484 }
485
496 StatusCode ObjectMetadata::Variable::read( const std::string& data ) {
497
498 //
499 // Tokenize the string using Boost:
500 //
501 boost::char_separator< char > separator( STRING_SEPARATOR, "",
502 boost::keep_empty_tokens );
503 boost::tokenizer< boost::char_separator< char > > tokens( data,
504 separator );
505 boost::tokenizer< boost::char_separator< char > >::const_iterator itr = tokens.begin();
506
507 // Check that we didn't reach the last token yet:
508 if( itr == tokens.end() ) {
509 REPORT_MESSAGE_WITH_CONTEXT( MSG::FATAL, "ObjectMetadata::Variable" )
510 << "The received data can not be parsed successfully: "
511 << data;
512 return StatusCode::FAILURE;
513 }
514
515 // Extract the name of the variable:
516 m_name = *itr; ++itr;
517
518 // Check that we didn't reach the last token yet:
519 if( itr == tokens.end() ) {
520 REPORT_MESSAGE_WITH_CONTEXT( MSG::FATAL, "ObjectMetadata::Variable" )
521 << "The received data can not be parsed successfully: "
522 << data;
523 return StatusCode::FAILURE;
524 }
525
526 // Extract the type of the variable:
527 m_type = *itr; ++itr;
528
529 // Check that we didn't reach the last token yet:
530 if( itr == tokens.end() ) {
531 REPORT_MESSAGE_WITH_CONTEXT( MSG::FATAL, "ObjectMetadata::Variable" )
532 << "The received data can not be parsed successfully: "
533 << data;
534 return StatusCode::FAILURE;
535 }
536
537 // Extract the documentation string of the variable:
538 m_doc = *itr; ++itr;
539
540 // Check that we didn't reach the last token yet:
541 if( itr == tokens.end() ) {
542 REPORT_MESSAGE_WITH_CONTEXT( MSG::FATAL, "ObjectMetadata::Variable" )
543 << "The received data can not be parsed successfully: "
544 << data;
545 return StatusCode::FAILURE;
546 }
547
548 // Extract the information of whether this variable is a primitive or not:
549 if( *itr == "0" ) {
550 m_primitive = false;
551 } else if( *itr == "1" ) {
552 m_primitive = true;
553 } else {
554 REPORT_MESSAGE_WITH_CONTEXT( MSG::FATAL, "ObjectMetadata::Variable" )
555 << "The received data can not be parsed successfully: "
556 << data;
557 return StatusCode::FAILURE;
558 }
559
560 return StatusCode::SUCCESS;
561 }
562
564
565 return ( ( name() == var.name() ) &&
566 ( type() == var.type() ) );
567 }
568
570
571 if( name() != var.name() ) {
572 return ( name() < var.name() );
573 } else {
574 return ( type() < var.type() );
575 }
576 }
577
578 const std::set< ObjectMetadata::Variable >& ObjectMetadata::variables() const {
579
580 return m_variables;
581 }
582
584 const ObjectMetadata& obj2 ) {
585
586 ObjectMetadata result( obj1 );
587 return result += obj2;
588 }
589
590} // namespace D3PD
Helpers for checking error return status codes and reporting errors.
#define REPORT_MESSAGE_WITH_CONTEXT(LVL, CONTEXT_NAME)
Report a message, with an explicitly specified context name.
#define CHECK(...)
Evaluate an expression and check for errors.
double length(const pvec &v)
Internal class keeping track of a single variable.
bool operator<(const Variable &var) const
Operator needed to use such objects in STL containers.
const std::string & type() const
Type name of the variable.
bool m_primitive
Flag showing whether the variable is a primitive.
StatusCode read(const std::string &data)
Read data from a "serialized" string.
void setDoc(std::string_view doc)
Set the description of the variable.
bool operator==(const Variable &var) const
Operator checking the equivalence of two variables.
std::string toString() const
Function "serializing" the variable information into a string.
std::string m_type
Full type name of the variable.
void setPrimitive(bool primitive)
Set whether the variable is a primitive.
const std::string & doc() const
Description of the variable.
const std::string & name() const
Name of the variable without its prefix.
static const char *const STRING_SEPARATOR
Character separating parts of the variable's metadata.
std::string m_name
Name of the variable without its prefix.
void setName(const std::string &name)
Set the name of the variable.
bool primitive() const
Flag showing whether the variable is a primitive.
void setType(const std::string &type)
Set the type name of the variable.
std::string m_doc
Description of the variable.
D3PD variable metadata handling class.
static const size_t RANDOM_NAME_POSTFIX_LENGTH
Length of the random string appended to the object name.
void clear()
Function clearing the object.
const std::string & name() const
Get the name of the D3PDObject that this object describes.
static const unsigned int SERIALIZER_VERSION
"Version number" of the serialized information
ObjectMetadata & operator+=(const ObjectMetadata &obj)
Operator merging the contents of two objects.
std::set< Variable > m_variables
The list of variables created by a D3PDObject.
const std::set< Variable > & variables() const
Function for accessing all the variables of the D3PDObject.
bool m_container
The D3PDObject describes a container.
ObjectMetadata & operator=(const ObjectMetadata &parent)
Assignment operator.
virtual StatusCode addVariable(const std::string &name, const std::type_info &ti, void *&ptr, std::string_view docstring="", const void *defval=0)
This function can be used to save the metadata about a D3PD variable.
StatusCode read(const std::string &data)
Function "de-serializing" the stored information from a string.
virtual StatusCode addDimensionedVariable(const std::string &name, const std::type_info &ti, void *&ptr, const std::string &dim, std::string_view docstring="", const void *defval=0)
The object doesn't support dimensioned variables at the moment, like most of the D3PDMaker code doesn...
std::string toString() const
Function "serializing" the stored information into a string.
std::string m_name
Name of the D3PDObject that this object describes.
void setPrefix(const std::string &prefix)
Set the prefix given to variables in this D3PDObject.
void setName(const std::string &name)
Set the name of the D3PDObject that this object describes.
ObjectMetadata & merge(const ObjectMetadata &obj)
Function merging the contents of two objects.
void setContainer(bool container)
Set whether the D3PDObject describes a container or not.
const std::string & prefix() const
Get the prefix given to variables in this D3PDObject.
std::string m_prefix
Prefix used by the D3PDObject.
static std::string objectName(const std::string &metaName)
Get the D3PDObject's name from the name of the metadata object.
ObjectMetadata()
Default constructor.
bool operator<(const ObjectMetadata &rhs) const
Operator needed to use such objects in ordered STL containers.
static const char *const STRING_SEPARATOR
Character separating parts of the object's metadata.
bool operator==(const ObjectMetadata &rhs) const
Equality operator.
bool container() const
Get whether the D3PDObject describes a container or not.
int count(std::string s, const std::string &regx)
count how many occurances of a regx are in a string
Definition hcg.cxx:148
Block filler tool for noisy FEB information.
StatusCode DummyInitAlg::initialize ATLAS_NOT_THREAD_SAFE()
Standard Gaudi initialize method.
ObjectMetadata operator+(const ObjectMetadata &obj1, const ObjectMetadata &obj2)
Operator for creating the sum of two metadata objects.
Definition merge.py:1