ATLAS Offline Software
Loading...
Searching...
No Matches
Control/xAODRootAccess/Root/Utils.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// STL include(s):
6#include <algorithm>
7#include <cctype>
8#include <functional>
9#include <regex>
10
11// ROOT include(s):
12#include <TError.h>
13#include <ROOT/RNTupleDescriptor.hxx>
14
15// EDM include(s):
17
18// Local include(s):
21
22
23namespace {
24
33 void removeDefaultTemplateParameters( std::string& name,
34 const std::string& vectorName ) {
35
36 size_t vecPos = 0;
37 while( ( vecPos = name.find( vectorName + "<", vecPos ) ) !=
38 std::string::npos ) {
39
40 // Update the position to point at the end of the search string:
41 vecPos += ( vectorName.size() + 1 );
42
43 // Look for "the comma" that we should remove everything
44 // after:
45 int open = 0;
46 size_t commaPos = std::string::npos;
47 for( size_t pos = vecPos; pos < name.size(); ++pos ) {
48 switch( name[ pos ] ) {
49 case '<':
50 ++open;
51 break;
52 case '>':
53 --open;
54 break;
55 case ',':
56 if( ! open ) {
57 commaPos = pos;
58 }
59 break;
60 default:
61 break;
62 }
63 if( commaPos != std::string::npos ) {
64 break;
65 }
66 }
67
68 // If we didn't find a comma, then let's give up:
69 if( commaPos == std::string::npos ) {
70 continue;
71 }
72
73 // If we did, then let's look for the closing '>' of the vector:
74 open = 0;
75 size_t closingPos = std::string::npos;
76 for( size_t pos = commaPos; pos < name.size(); ++pos ) {
77 switch( name[ pos ] ) {
78 case '<':
79 ++open;
80 break;
81 case '>':
82 if( ! open ) {
83 closingPos = pos;
84 break;
85 }
86 --open;
87 break;
88 default:
89 break;
90 }
91 if( closingPos != std::string::npos ) {
92 break;
93 }
94 }
95
96 // It's bad if we didn't find the closing '>'...
97 if( closingPos == std::string::npos ) {
98 ::Error( "removeDefaultTemplateParameters",
99 XAOD_MESSAGE( "Couldn't find closing '>' in name %s" ),
100 name.c_str() );
101 return;
102 }
103
104 // Remove the identified part of the string:
105 name.erase( commaPos, closingPos - commaPos );
106 }
107
108 return;
109 }
110
111} // private namespace
112
113namespace xAOD {
114
115 namespace Utils {
116
128 SG::sgkey_t hash( const std::string& name ) {
129
130 static constexpr SG::sgkey_t MASK = (~static_cast<SG::sgkey_t>(0)) >> 2;
131
132 // The helper object:
133 static const std::hash< std::string > helper;
134 // Let the helper do the work:
135 return ( static_cast< SG::sgkey_t >( helper( name ) ) & MASK );
136 }
137
147 std::string dynBranchPrefix( const std::string& key ) {
148
149 // Make a copy of the key that we can modify:
150 std::string result = key;
151
152 // If it ends in a dot, then let's exchange that dot for
153 // "Dyn.":
154 if( result[ result.size() - 1 ] == '.' ) {
155 result.replace( result.size() - 1, 1, "Dyn." );
156 }
157 // If it doesn't end in a dot, then let's just add "Dyn." at
158 // the end, and be done with it:
159 else {
160 result += "Dyn.";
161 }
162
163 return result;
164 }
165
173 std::string dynFieldPrefix( const std::string& key ) {
174 // Make a copy of the key that we can modify:
175 std::string result = key;
176
177 // If it ends in a colon, then let's exchange that colon for
178 // "Dyn:":
179 if( result[ result.size() - 1 ] == ':' ) {
180 result.replace( result.size() - 1, 1, "Dyn:" );
181 }
182 // If it doesn't end in a colon, then let's just add "Dyn:" at
183 // the end:
184 else {
185 result += "Dyn:";
186 }
187
188 return result;
189 }
190
197 const std::type_info& getTypeInfo( EDataType type ) {
198
199 switch( type ) {
200
201 case kChar_t:
202 case kchar:
203 return typeid( Char_t );
204 case kUChar_t:
205 return typeid( UChar_t );
206 case kShort_t:
207 return typeid( Short_t );
208 case kUShort_t:
209 return typeid( UShort_t );
210 case kInt_t:
211 case kCounter:
212 return typeid( Int_t );
213 case kUInt_t:
214 case kBits:
215 case kDataTypeAliasUnsigned_t:
216 return typeid( UInt_t );
217 case kLong_t:
218 return typeid( Long_t );
219 case kULong_t:
220 return typeid( ULong_t );
221 case kFloat_t:
222 return typeid( Float_t );
223 case kDouble_t:
224 return typeid( Double_t );
225 case kDouble32_t:
226 return typeid( Double32_t );
227 case kBool_t:
228 return typeid( Bool_t );
229 case kLong64_t:
230 return typeid( Long64_t );
231 case kULong64_t:
232 return typeid( ULong64_t );
233 case kFloat16_t:
234 return typeid( Float16_t );
235 case kCharStar:
236 return typeid( char* );
237 case kVoid_t:
238 return typeid( void );
239 default:
240 ::Error( "xAOD::Utils::getTypeInfo",
241 XAOD_MESSAGE( "Unknown data type (%i) received" ),
242 static_cast< int >( type ) );
243 return typeid( void );
244 }
245 }
246
248#define TYPE_CHECK_INSTANTIATE(MACRO) \
249 MACRO(std::int8_t) \
250 MACRO(std::uint8_t) \
251 MACRO(std::int16_t) \
252 MACRO(std::uint16_t) \
253 MACRO(std::int32_t) \
254 MACRO(std::uint32_t) \
255 MACRO(std::int64_t) \
256 MACRO(std::uint64_t) \
257 MACRO(char) \
258 MACRO(float) \
259 MACRO(double) \
260 MACRO(bool)
261
263#define GETTYPEINFO_SPECIALIZE(TYPE) \
264 if(typeName == #TYPE) { \
265 return typeid(TYPE); \
266 }
267
268 const std::type_info& getTypeInfo(std::string_view typeName) {
270 ::Error("xAOD::Utils::getTypeInfo",
271 XAOD_MESSAGE("Unknown data type (%s) received"),
272 typeName.data());
273 return typeid(void);
274 }
275
276#undef GETTYPEINFO_SPECIALIZE
277
278#define ISPRIMITIVETYPE_SPECIALIZE(TYPE) \
279 if(typeName == #TYPE) { \
280 return true; \
281 }
282
283 bool isPrimitiveType(std::string_view typeName) {
285 return false;
286 }
287
288#undef ISPRIMITIVETYPE_SPECIALIZE
289#undef TYPE_CHECK_INSTANTIATE
290
298 char rootType( char typeidType ) {
299
300 // Do the hard-coded translation:
301 switch( typeidType ) {
302
303 case 'c':
304 return 'B';
305 break;
306 case 'h':
307 return 'b';
308 break;
309 case 's':
310 return 'S';
311 break;
312 case 't':
313 return 's';
314 break;
315 case 'i':
316 return 'I';
317 break;
318 case 'j':
319 return 'i';
320 break;
321 case 'f':
322 return 'F';
323 break;
324 case 'd':
325 return 'D';
326 break;
327 case 'x':
328 return 'L';
329 break;
330 case 'y':
331 case 'm': // Not sure how platform-independent this one is...
332 return 'l';
333 break;
334 case 'b':
335 return 'O';
336 break;
337 }
338
339 // If we didn't find this type:
340 Error( "xAOD::Utils::rootType",
341 XAOD_MESSAGE( "Received an unknown type: %c" ), typeidType );
342 return '\0';
343 }
344
357 std::string getTypeName( const std::type_info& ti ) {
358
359 // Get the "raw" type name:
360 std::string result = AthContainers_detail::typeinfoName( ti );
361
362 // If there are no "tricky" classes in the name, then we're done
363 // already:
364 if( ( result.find( "DataVector<" ) == std::string::npos ) &&
365 ( result.find( "std::vector<" ) == std::string::npos ) &&
366 ( result.find( "std::__1::vector<") == std::string::npos ) ) {
367 return result;
368 }
369
370 // Deal with the vector types:
371 removeDefaultTemplateParameters( result, "DataVector" );
372 removeDefaultTemplateParameters( result, "std::vector" );
373 removeDefaultTemplateParameters( result, "std::__1::vector" );
374
375 // Make sure that no ">>" parts are left in the type name:
376 size_t pos = 0;
377 while( ( pos = result.find( ">>" ) ) != std::string::npos ) {
378 result.replace( pos, 2, "> >" );
379 }
380
381 // Remove all "__1" namespaces from the type name:
382 while( ( pos = result.find( "__1::" ) ) != std::string::npos ) {
383 result.replace( pos, 5, "" );
384 }
385
386 // Return the massaged name:
387 return result;
388 }
389
397 std::string getFirstBranchMatch( TTree * tree,
398 const std::string& pre ) {
399 const TObjArray * pBranches = tree->GetListOfBranches();
400 const std::regex pattern( ".*" + pre + ".*" );
401
402 for( int i = 0, nLast = pBranches->GetLast(); i <= nLast; ++i ) {
403 const std::string name = pBranches->At(i)->GetName();
404
405 if( std::regex_match( name, pattern ) )
406 return name;
407
408 }
409
410 return pre;
411 }
412
426 std::string getFieldName( const ROOT::RNTupleDescriptor& descriptor,
427 const std::string& key ) {
428
429 std::string fieldName = key;
430 if( fieldName.ends_with( "Aux." ) ) {
431 fieldName.back() = ':';
432 }
433 if( descriptor.FindFieldId( fieldName ) !=
434 ROOT::kInvalidDescriptorId ) {
435 return fieldName;
436 }
437
438 // Replace the characters the same way as Athena does when writing.
439 fieldName = key;
440 std::replace_if( fieldName.begin(), fieldName.end(),
441 []( unsigned char c ) { return !std::isalnum( c ); },
442 '_' );
443 if( fieldName.ends_with( "Aux_" ) ) {
444 fieldName.back() = ':';
445 }
446 return fieldName;
447 }
448
449 } // namespace Utils
450
451} // namespace xAOD
#define TYPE_CHECK_INSTANTIATE(MACRO)
Macro instantiating another macro for all usual "primitive" types.
#define ISPRIMITIVETYPE_SPECIALIZE(TYPE)
#define GETTYPEINFO_SPECIALIZE(TYPE)
Macro returning the type info for a given type name.
#define XAOD_MESSAGE(MESSAGE)
Simple macro for printing error/verbose messages.
Helper for emitting error messages.
uint32_t sgkey_t
Type used for hashed StoreGate key+CLID pairs.
Definition sgkey_t.h:32
@ open
Definition BinningType.h:40
const std::type_info & getTypeInfo(EDataType type)
This function is used when reading a primitive branch from an input file without the user explicitly ...
SG::sgkey_t hash(const std::string &name)
This function provides a hashed version of the key (branch) names used in the xAOD file,...
std::string dynBranchPrefix(const std::string &key)
This function is used to figure out what to name dynamic auxiliary branches coming from a container c...
char rootType(char typeidType)
This function is used internally in the code when creating primitive dynamic auxiliary branches.
std::string getFieldName(const ROOT::RNTupleDescriptor &descriptor, const std::string &key)
This function is used to find the name of the field in an RNTuple that stores the object with a given...
std::string getFirstBranchMatch(TTree *tree, const std::string &pre)
This function is used to search for a branch in a TTree that contains a given substring.
bool isPrimitiveType(std::string_view typeName)
Check if the type name describes a primitive type.
std::string getTypeName(const std::type_info &ti)
This function is necessary in order to create type names that ROOT can understand.
std::string dynFieldPrefix(const std::string &key)
This function is used to figure out what to name dynamic auxiliary field coming from a container call...
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
TChain * tree