The Gaudi Framework  v33r1 (b1225454)
TupleObj.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 // ============================================================================
12 // Include files
13 // ============================================================================
14 // STD & STL
15 // ============================================================================
16 #include <algorithm>
17 #include <cstdarg>
18 #include <map>
19 // ============================================================================
20 // GaudiKernel
21 // ============================================================================
23 // ============================================================================
24 // GaudiAlg
25 // ============================================================================
26 #include "GaudiAlg/TupleObj.h"
27 #include "GaudiAlg/Tuples.h"
28 // ============================================================================
29 // Boost
30 // ============================================================================
31 #include "boost/integer_traits.hpp"
32 // ============================================================================
40 // ============================================================================
41 
42 namespace {
43 
44  template <typename T>
45  struct tuple_type_;
46 
47  template <>
48  struct tuple_type_<typename Tuples::TupleObj::Float> {
49  static constexpr const char* fmt = "F";
50  static constexpr const char* typ = "floats";
51  };
52  template <>
53  struct tuple_type_<typename Tuples::TupleObj::Double> {
54  static constexpr const char* fmt = "D";
55  static constexpr const char* typ = "doubles";
56  };
57  template <>
58  struct tuple_type_<typename Tuples::TupleObj::Bool> {
59  static constexpr const char* fmt = "I";
60  static constexpr const char* typ = "bools";
61  };
62  template <>
63  struct tuple_type_<typename Tuples::TupleObj::Char> {
64  static constexpr const char* fmt = "I";
65  static constexpr const char* typ = "chars";
66  };
67  template <>
68  struct tuple_type_<typename Tuples::TupleObj::UChar> {
69  static constexpr const char* fmt = "I";
70  static constexpr const char* typ = "uchars";
71  };
72  template <>
73  struct tuple_type_<typename Tuples::TupleObj::Short> {
74  static constexpr const char* fmt = "I";
75  static constexpr const char* typ = "shorts";
76  };
77  template <>
78  struct tuple_type_<typename Tuples::TupleObj::UShort> {
79  static constexpr const char* fmt = "I";
80  static constexpr const char* typ = "ushorts";
81  };
82  template <>
83  struct tuple_type_<typename Tuples::TupleObj::Int> {
84  static constexpr const char* fmt = "I";
85  static constexpr const char* typ = "ints";
86  };
87  template <>
88  struct tuple_type_<typename Tuples::TupleObj::UInt> {
89  static constexpr const char* fmt = "I";
90  static constexpr const char* typ = "uints";
91  };
92  template <>
93  struct tuple_type_<typename Tuples::TupleObj::LongLong> {
94  static constexpr const char* fmt = "ULL";
95  static constexpr const char* typ = "longlongs";
96  };
97  template <>
98  struct tuple_type_<typename Tuples::TupleObj::ULongLong> {
99  static constexpr const char* fmt = "ULL";
100  static constexpr const char* typ = "ulonglongs";
101  };
102  template <>
103  struct tuple_type_<typename Tuples::TupleObj::Address> {
104  static constexpr const char* fmt = "IOpaqueAddress*";
105  static constexpr const char* typ = "addresses";
106  };
107  template <>
108  struct tuple_type_<typename Tuples::TupleObj::FArray> {
109  static constexpr const char* fmt = "FArray";
110  static constexpr const char* typ = "farray";
111  };
112  template <>
113  struct tuple_type_<typename Tuples::TupleObj::FMatrix> {
114  static constexpr const char* fmt = "FMatrix";
115  static constexpr const char* typ = "fmatrix";
116  };
117 
118  // helper functions to simplify things...
119  template <typename C, typename AddItem>
120  typename C::mapped_type::pointer create_( Tuples::TupleObj* parent, C& container, const std::string& name,
121  AddItem addItem ) {
122  using element_t = typename C::mapped_type::element_type;
123  using map_t = struct tuple_type_<element_t>;
124  auto item = container.emplace( name, std::make_unique<element_t>() );
125  if ( !item.second ) {
126  parent->Error( std::string{map_t::typ} + " ('" + name + "'): item is not inserted" )
127  .ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ );
128  }
129  StatusCode sc = addItem( name, *( item.first->second ) );
130  if ( sc.isFailure() ) {
131  parent->Error( std::string{map_t::typ} + " ('" + name + "'): item is not added", sc )
132  .ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ );
133  }
134  if ( !parent->addItem( name, map_t::fmt ) ) {
135  parent->Error( std::string{map_t::typ} + " ('" + name + "'): item is not unique" )
136  .ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ );
137  }
138  return item.first->second.get();
139  }
140 
141  template <typename C, typename... ExtraArgs>
142  typename C::mapped_type::pointer find_or_create( Tuples::TupleObj* parent, const std::string& name, C& map,
143  ExtraArgs&&... ea ) {
144  using pointer = typename C::mapped_type::pointer;
145  using reference = std::add_lvalue_reference_t<std::remove_pointer_t<pointer>>;
146  auto found = map.find( name );
147  return found != map.end() ? found->second.get()
148  : create_( parent, map, name, [&]( const std::string& n, reference i ) {
149  return parent->tuple()->addItem( n, i, std::forward<ExtraArgs>( ea )... );
150  } );
151  }
152 
153  template <typename Container, typename UT, typename... ExtraArgs>
154  StatusCode column_( Tuples::TupleObj* parent, Container& container, const std::string& name, UT&& value,
155  ExtraArgs&&... ea ) {
156  if ( parent->invalid() ) return Tuples::ErrorCodes::InvalidTuple;
157  auto item = find_or_create( parent, name, container, std::forward<ExtraArgs>( ea )... );
158  if ( !item ) return Tuples::ErrorCodes::InvalidColumn;
159  *item = std::forward<UT>( value );
160  return StatusCode::SUCCESS;
161  }
162 
163  struct TuplesCategory : StatusCode::Category {
164  const char* name() const override { return "Tuples"; }
165 
166  bool isRecoverable( StatusCode::code_t ) const override { return false; }
167 
168  std::string message( StatusCode::code_t code ) const override {
169  switch ( static_cast<Tuples::ErrorCodes>( code ) ) {
171  return "InvalidTuple";
173  return "InvalidColumn";
175  return "InvalidOperation";
177  return "InvalidObject";
179  return "InvalidItem";
181  return "TruncateValue";
182  default:
183  return StatusCode::default_category().message( code );
184  }
185  }
186  };
187 } // namespace
188 
189 STATUSCODE_ENUM_IMPL( Tuples::ErrorCodes, TuplesCategory )
190 
191 namespace Tuples {
192  namespace Local {
193  class Counter final {
194  public:
195  // constructor
196  Counter( std::string msg = " Misbalance " ) : m_message( std::move( msg ) ) {}
197  // destructor
198  ~Counter() { report(); }
199  // make the increment
200  long increment( const std::string& object ) { return ++m_map[object]; }
201  // make the decrement
202  long decrement( const std::string& object ) { return --m_map[object]; }
203  // current count
204  long counts( const std::string& object ) const { return m_map.at( object ); }
205  // make a report
206  void report() const {
207  for ( auto& entry : m_map ) {
208  if ( entry.second != 0 )
209  std::cout << "Tuples::TupleObj WARNING " << m_message << "'" << entry.first << "' Counts = " << entry.second
210  << std::endl;
211  }
212  };
213 
214  private:
217  };
218 
224  static Counter s_InstanceCounter{" Create/Destroy (mis)balance "};
225  } // namespace Local
226 } // namespace Tuples
227 // ============================================================================
228 // Standard constructor
229 // ============================================================================
231  //
232  : m_name( std::move( name ) ), m_tuple( tuple ), m_clid( clid ), m_type( type ) {
233  // make counts
234  Tuples::Local::s_InstanceCounter.increment( m_name );
235 }
236 // ============================================================================
237 // destructor
238 // ============================================================================
240  // make counts
241  Tuples::Local::s_InstanceCounter.decrement( m_name );
242 }
243 // ============================================================================
244 // write a record to NTuple
245 // ============================================================================
247  if ( invalid() ) return ErrorCodes::InvalidTuple;
248  return tuple()->write();
249 }
250 // ============================================================================
251 namespace {
256  std::vector<std::string> tokenize( std::string_view value, std::string_view separators = " " ) {
258  auto it1 = value.begin();
259  auto it2 = value.begin();
260  while ( value.end() != it1 && value.end() != it2 ) {
261  it2 = std::find_first_of( it1, value.end(), separators.begin(), separators.end() );
262  if ( it2 != it1 ) {
263  tokens.emplace_back( value, it1 - value.begin(), it2 - it1 );
264  it1 = it2;
265  } else {
266  ++it1;
267  }
268  }
269  return tokens;
270  }
271 } // namespace
272 // ============================================================================
274  // check the underlying tuple
275  if ( invalid() ) return ErrorCodes::InvalidTuple;
276  // decode format string into tokens
277  auto tokens = tokenize( format, " ,;" );
279  va_list valist;
280  va_start( valist, format );
281  // loop over all tokens
283  for ( auto token = tokens.cbegin(); tokens.cend() != token && status.isSuccess(); ++token ) {
284  double val = va_arg( valist, double );
285  status = column( *token, val );
286  if ( status.isFailure() )
287  Error( "fill(): Can not add column '" + *token + "' " ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ );
288  }
289  // mandatory !!!
290  va_end( valist );
291  //
292  return status;
293 }
294 
295 // ============================================================================
296 // put IOpaqueAddress in NTuple (has sense only for Event tag collection Ntuples)
297 // ============================================================================
299  if ( !evtColType() ) return ErrorCodes::InvalidOperation;
300  if ( !address ) return Error( "column('" + name + "') IOpaqueAddress* is NULL!", ErrorCodes::InvalidObject );
301  return column_( this, m_addresses, name, address );
302 }
303 
304 // ============================================================================
305 // put IOpaqueAddress in NTuple (has sense only for Event tag collection Ntuples)
306 // ============================================================================
307 StatusCode Tuples::TupleObj::column( IOpaqueAddress* address ) { return column( "Address", address ); }
308 
309 // ============================================================================
311  return column_( this, m_floats, name, value );
312 }
313 // ============================================================================
315  return column_( this, m_doubles, name, value );
316 }
317 // ============================================================================
319  return column_( this, m_chars, name, value );
320 }
321 // ============================================================================
322 StatusCode Tuples::TupleObj::column( const std::string& name, char value, char minv, char maxv ) {
323  return column_( this, m_chars, name, value, minv, maxv );
324 }
325 // ============================================================================
326 StatusCode Tuples::TupleObj::column( const std::string& name, unsigned char value ) {
327  return column_( this, m_uchars, name, value );
328 }
329 // ============================================================================
330 StatusCode Tuples::TupleObj::column( const std::string& name, unsigned char value, unsigned char minv,
331  unsigned char maxv ) {
332  return column_( this, m_uchars, name, value, minv, maxv );
333 }
334 // ============================================================================
336  return column_( this, m_shorts, name, value );
337 }
338 // ============================================================================
339 StatusCode Tuples::TupleObj::column( const std::string& name, const short value, const short minv, const short maxv ) {
340  return column_( this, m_shorts, name, value, minv, maxv );
341 }
342 // ============================================================================
343 StatusCode Tuples::TupleObj::column( const std::string& name, const unsigned short value ) {
344  return column_( this, m_ushorts, name, value );
345 }
346 // ============================================================================
347 StatusCode Tuples::TupleObj::column( const std::string& name, unsigned short value, unsigned short minv,
348  unsigned short maxv ) {
349  return column_( this, m_ushorts, name, value, minv, maxv );
350 }
351 // ============================================================================
353  return column_( this, m_ints, name, value );
354 }
355 // ============================================================================
356 StatusCode Tuples::TupleObj::column( const std::string& name, int value, int minv, int maxv ) {
357  return column_( this, m_ints, name, value, minv, maxv );
358 }
359 // ============================================================================
361  return find_or_create( this, name, m_ints, minv, maxv );
362 }
363 // ============================================================================
364 StatusCode Tuples::TupleObj::column( const std::string& name, unsigned int value ) {
365  return column_( this, m_uints, name, value );
366 }
367 // ============================================================================
368 StatusCode Tuples::TupleObj::column( const std::string& name, unsigned int value, unsigned int minv,
369  unsigned int maxv ) {
370  return column_( this, m_uints, name, value, minv, maxv );
371 }
372 // ============================================================================
374  Warning( "'long' has different sizes on 32/64 bit systems. Casting '" + name + "' to 'long long'",
376  .ignore();
377  return column( name, static_cast<long long>( value ) );
378 }
379 // ============================================================================
380 StatusCode Tuples::TupleObj::column( const std::string& name, const long value, const long minv, const long maxv ) {
381  Warning( "'long' has different sizes on 32/64 bit systems. Casting '" + name + "' to 'long long'",
383  .ignore();
384  return column( name, static_cast<long long>( value ), static_cast<long long>( minv ),
385  static_cast<long long>( maxv ) );
386 }
387 // ============================================================================
388 StatusCode Tuples::TupleObj::column( const std::string& name, const unsigned long value ) {
389  Warning( "'unsigned long' has different sizes on 32/64 bit systems. Casting '" + name + "' to 'unsigned long long'",
391  .ignore();
392  return column( name, static_cast<unsigned long long>( value ) );
393 }
394 // ============================================================================
395 StatusCode Tuples::TupleObj::column( const std::string& name, const unsigned long value, const unsigned long minv,
396  const unsigned long maxv ) {
397  Warning( "'unsigned long' has different sizes on 32/64 bit systems. Casting '" + name + "' to 'unsigned long long'",
399  .ignore();
400  return column( name, static_cast<unsigned long long>( value ), static_cast<unsigned long long>( minv ),
401  static_cast<unsigned long long>( maxv ) );
402 }
403 // ============================================================================
404 StatusCode Tuples::TupleObj::column( const std::string& name, const long long value ) {
405  return column_( this, m_longlongs, name, value );
406 }
407 // ============================================================================
408 StatusCode Tuples::TupleObj::column( const std::string& name, long long value, long long minv, long long maxv ) {
409  return column_( this, m_longlongs, name, value, minv, maxv );
410 }
411 // ============================================================================
412 StatusCode Tuples::TupleObj::column( const std::string& name, unsigned long long value ) {
413  return column_( this, m_ulonglongs, name, value );
414 }
415 // ============================================================================
416 StatusCode Tuples::TupleObj::column( const std::string& name, unsigned long long value, unsigned long long minv,
417  unsigned long long maxv ) {
418  return column_( this, m_ulonglongs, name, value, minv, maxv );
419 }
420 // ============================================================================
422  return column_( this, m_bools, name, value );
423 }
424 // ============================================================================
425 // retrieve (book on demand) array-items for ntuple
426 // ============================================================================
428  // existing array ?
429  auto found = m_farrays.find( name );
430  if ( m_farrays.end() != found ) return found->second.get();
431  return create_( this, m_farrays, name,
432  [&]( const std::string& n, FArray& i ) { return this->tuple()->addIndexedItem( n, *length, i ); } );
433 }
434 // ============================================================================
435 // retrieve (book on demand) array-items for ntuple (fixed)
436 // ============================================================================
438  // existing array ?
439  auto found = m_arraysf.find( name );
440  if ( m_arraysf.end() != found ) return found->second.get();
441  return create_( this, m_arraysf, name,
442  [&]( const std::string& n, FArray& i ) { return this->tuple()->addItem( n, rows, i ); } );
443 }
444 // ============================================================================
445 // retrieve (book on demand) matrix-items for ntuple
446 // ============================================================================
448  const Tuples::TupleObj::MIndex& cols ) {
449  // existing array ?
450  auto found = m_fmatrices.find( name );
451  if ( m_fmatrices.end() != found ) return found->second.get();
452  return create_( this, m_fmatrices, name, [&]( const std::string& n, FMatrix& i ) {
453  return this->tuple()->addIndexedItem( n, *length, cols, i );
454  } );
455 }
456 // ============================================================================
457 // retrieve (book on demand) matrix-items for ntuple (fixed)
458 // ============================================================================
460  const Tuples::TupleObj::MIndex& cols ) {
461  // existing array ?
462  auto found = m_matricesf.find( name );
463  if ( m_matricesf.end() != found ) return found->second.get();
464  return create_( this, m_matricesf, name,
465  [&]( const std::string& n, FMatrix& i ) { return this->tuple()->addItem( n, rows, cols, i ); } );
466 }
467 // ============================================================================
468 // The END
469 // ============================================================================
Int * ints(const std::string &name, int minv, int maxv)
get the column
Definition: TupleObj.cpp:360
long decrement(const std::string &object)
Definition: TupleObj.cpp:202
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
Definition: MsgStream.cpp:119
Header file for class TupleObj.
Class acting as a smart pointer holding a N tuple _Item.
Definition: NTuple.h:62
StatusCode fill(const char *format...)
Set the values for several columns simultaneously.
Definition: TupleObj.cpp:273
The category assigned to a StatusCode.
Definition: StatusCode.h:78
StatusCode column(const std::string &name, float value)
Set the value for selected tuple column.
Definition: TupleObj.cpp:310
T endl(T... args)
ErrorCodes
Tuple error codes.
Definition: TupleObj.h:101
constexpr static const auto SUCCESS
Definition: StatusCode.h:100
virtual const char * name() const =0
Name of the category.
STL namespace.
T cend(T... args)
void report() const
Definition: TupleObj.cpp:206
unsigned short MIndex
Definition: TupleObj.h:255
std::string m_name
name
Definition: TupleObj.h:1943
Counter(std::string msg=" Misbalance ")
Definition: TupleObj.cpp:196
STL class.
T at(T... args)
struct GAUDI_API map
Parametrisation class for map-like implementation.
A simple wrapper class over standard Gaudi NTuple::Tuple facility.
Definition: TupleObj.h:209
TupleObj(std::string name, NTuple::Tuple *tuple, const CLID &clid=CLID_ColumnWiseTuple, const Tuples::Type type=Tuples::NTUPLE)
Standard constructor.
Definition: TupleObj.cpp:230
virtual std::string message(code_t code) const
Description for code within this category.
Definition: StatusCode.h:86
#define STATUSCODE_ENUM_IMPL(...)
Assign a category to the StatusCode enum declared with STATUSCODE_ENUM_DECL( ENUM )
Definition: StatusCode.h:346
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:61
virtual bool isRecoverable(code_t code) const
Is code considered recoverable ?
Definition: StatusCode.h:93
static const Category & default_category() noexcept
Default Gaudi StatusCode category.
Definition: StatusCode.h:361
std::map< std::string, long > m_map
Definition: TupleObj.cpp:212
T find_first_of(T... args)
StatusCode write()
write a record to NTuple
Definition: TupleObj.cpp:246
long counts(const std::string &object) const
Definition: TupleObj.cpp:204
unsigned int CLID
Class ID definition.
Definition: ClassID.h:18
bool isSuccess() const
Definition: StatusCode.h:365
Abstract base class which allows the user to interact with the actual N tuple implementation.
Definition: NTuple.h:385
virtual ~TupleObj()
Definition: TupleObj.cpp:239
FArray * fArray(const std::string &name, Int *item)
get the column
Definition: TupleObj.cpp:427
const StatusCode & ignore() const
Ignore/check StatusCode.
Definition: StatusCode.h:168
T begin(T... args)
const Gaudi::Algorithm & parent
FMatrix * fMatrix(const std::string &name, Int *item, const MIndex &cols)
get the column
Definition: TupleObj.cpp:447
bool isFailure() const
Definition: StatusCode.h:145
Opaque address interface definition.
Class acting as a smart pointer holding a N tuple _Item.
Definition: NTuple.h:58
std::string m_message
Definition: TupleObj.cpp:216
Class acting as a smart pointer holding a N tuple _Item.
Definition: NTuple.h:60
Type
the list of available types for ntuples
Definition: TupleObj.h:89
long increment(const std::string &object)
Definition: TupleObj.cpp:200
unsigned long code_t
type of StatusCode value
Definition: StatusCode.h:67
General namespace for Tuple properties.
Definition: Maps.h:43
T emplace_back(T... args)