The Gaudi Framework  v33r0 (d5ea422b)
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 ) { parent->Error( std::string{map_t::typ} + " ('" + name + "'): item is not inserted" ); }
126  StatusCode sc = addItem( name, *( item.first->second ) );
127  if ( sc.isFailure() ) { parent->Error( std::string{map_t::typ} + " ('" + name + "'): item is not added", sc ); }
128  if ( !parent->addItem( name, map_t::fmt ) ) {
129  parent->Error( std::string{map_t::typ} + " ('" + name + "'): item is not unique" );
130  }
131  return item.first->second.get();
132  }
133 
134  template <typename C, typename... ExtraArgs>
135  typename C::mapped_type::pointer find_or_create( Tuples::TupleObj* parent, const std::string& name, C& map,
136  ExtraArgs&&... ea ) {
137  using pointer = typename C::mapped_type::pointer;
138  using reference = std::add_lvalue_reference_t<std::remove_pointer_t<pointer>>;
139  auto found = map.find( name );
140  return found != map.end() ? found->second.get()
141  : create_( parent, map, name, [&]( const std::string& n, reference i ) {
142  return parent->tuple()->addItem( n, i, std::forward<ExtraArgs>( ea )... );
143  } );
144  }
145 
146  template <typename Container, typename UT, typename... ExtraArgs>
147  StatusCode column_( Tuples::TupleObj* parent, Container& container, const std::string& name, UT&& value,
148  ExtraArgs&&... ea ) {
149  if ( parent->invalid() ) return Tuples::ErrorCodes::InvalidTuple;
150  auto item = find_or_create( parent, name, container, std::forward<ExtraArgs>( ea )... );
151  if ( !item ) return Tuples::ErrorCodes::InvalidColumn;
152  *item = std::forward<UT>( value );
153  return StatusCode::SUCCESS;
154  }
155 
156  struct TuplesCategory : StatusCode::Category {
157  const char* name() const override { return "Tuples"; }
158 
159  bool isRecoverable( StatusCode::code_t ) const override { return false; }
160 
161  std::string message( StatusCode::code_t code ) const override {
162  switch ( static_cast<Tuples::ErrorCodes>( code ) ) {
164  return "InvalidTuple";
166  return "InvalidColumn";
168  return "InvalidOperation";
170  return "InvalidObject";
172  return "InvalidItem";
174  return "TruncateValue";
175  default:
176  return StatusCode::default_category().message( code );
177  }
178  }
179  };
180 } // namespace
181 
182 STATUSCODE_ENUM_IMPL( Tuples::ErrorCodes, TuplesCategory )
183 
184 namespace Tuples {
185  namespace Local {
186  class Counter final {
187  public:
188  // constructor
189  Counter( std::string msg = " Misbalance " ) : m_message( std::move( msg ) ) {}
190  // destructor
191  ~Counter() { report(); }
192  // make the increment
193  long increment( const std::string& object ) { return ++m_map[object]; }
194  // make the decrement
195  long decrement( const std::string& object ) { return --m_map[object]; }
196  // current count
197  long counts( const std::string& object ) const { return m_map.at( object ); }
198  // make a report
199  void report() const {
200  for ( auto& entry : m_map ) {
201  if ( entry.second != 0 )
202  std::cout << "Tuples::TupleObj WARNING " << m_message << "'" << entry.first << "' Counts = " << entry.second
203  << std::endl;
204  }
205  };
206 
207  private:
210  };
211 
217  static Counter s_InstanceCounter{" Create/Destroy (mis)balance "};
218  } // namespace Local
219 } // namespace Tuples
220 // ============================================================================
221 // Standard constructor
222 // ============================================================================
224  //
225  : m_name( std::move( name ) ), m_tuple( tuple ), m_clid( clid ), m_type( type ) {
226  // make counts
227  Tuples::Local::s_InstanceCounter.increment( m_name );
228 }
229 // ============================================================================
230 // destructor
231 // ============================================================================
233  // make counts
234  Tuples::Local::s_InstanceCounter.decrement( m_name );
235 }
236 // ============================================================================
237 // write a record to NTuple
238 // ============================================================================
240  if ( invalid() ) return ErrorCodes::InvalidTuple;
241  return tuple()->write();
242 }
243 // ============================================================================
244 namespace {
249  std::vector<std::string> tokenize( const std::string& value, const std::string& separators = " " ) {
251  auto it1 = value.begin();
252  auto it2 = value.begin();
253  while ( value.end() != it1 && value.end() != it2 ) {
254  it2 = std::find_first_of( it1, value.end(), separators.begin(), separators.end() );
255  if ( it2 != it1 ) {
256  tokens.emplace_back( value, it1 - value.begin(), it2 - it1 );
257  it1 = it2;
258  } else {
259  ++it1;
260  }
261  }
262  return tokens;
263  }
264 } // namespace
265 // ============================================================================
267  // check the underlying tuple
268  if ( invalid() ) return ErrorCodes::InvalidTuple;
269  // decode format string into tokens
270  auto tokens = tokenize( format, " ,;" );
272  va_list valist;
273  va_start( valist, format );
274  // loop over all tokens
276  for ( auto token = tokens.cbegin(); tokens.cend() != token && status.isSuccess(); ++token ) {
277  double val = va_arg( valist, double );
278  status = column( *token, val );
279  if ( status.isFailure() ) Error( "fill(): Can not add column '" + *token + "' " );
280  }
281  // mandatory !!!
282  va_end( valist );
283  //
284  return status;
285 }
286 
287 // ============================================================================
288 // put IOpaqueAddress in NTuple (has sense only for Event tag collection Ntuples)
289 // ============================================================================
291  if ( !evtColType() ) return ErrorCodes::InvalidOperation;
292  if ( !address ) return Error( "column('" + name + "') IOpaqueAddress* is NULL!", ErrorCodes::InvalidObject );
293  return column_( this, m_addresses, name, address );
294 }
295 
296 // ============================================================================
297 // put IOpaqueAddress in NTuple (has sense only for Event tag collection Ntuples)
298 // ============================================================================
299 StatusCode Tuples::TupleObj::column( IOpaqueAddress* address ) { return column( "Address", address ); }
300 
301 // ============================================================================
303  return column_( this, m_floats, name, value );
304 }
305 // ============================================================================
307  return column_( this, m_doubles, name, value );
308 }
309 // ============================================================================
311  return column_( this, m_chars, name, value );
312 }
313 // ============================================================================
314 StatusCode Tuples::TupleObj::column( const std::string& name, char value, char minv, char maxv ) {
315  return column_( this, m_chars, name, value, minv, maxv );
316 }
317 // ============================================================================
318 StatusCode Tuples::TupleObj::column( const std::string& name, unsigned char value ) {
319  return column_( this, m_uchars, name, value );
320 }
321 // ============================================================================
322 StatusCode Tuples::TupleObj::column( const std::string& name, unsigned char value, unsigned char minv,
323  unsigned char maxv ) {
324  return column_( this, m_uchars, name, value, minv, maxv );
325 }
326 // ============================================================================
328  return column_( this, m_shorts, name, value );
329 }
330 // ============================================================================
331 StatusCode Tuples::TupleObj::column( const std::string& name, const short value, const short minv, const short maxv ) {
332  return column_( this, m_shorts, name, value, minv, maxv );
333 }
334 // ============================================================================
335 StatusCode Tuples::TupleObj::column( const std::string& name, const unsigned short value ) {
336  return column_( this, m_ushorts, name, value );
337 }
338 // ============================================================================
339 StatusCode Tuples::TupleObj::column( const std::string& name, unsigned short value, unsigned short minv,
340  unsigned short maxv ) {
341  return column_( this, m_ushorts, name, value, minv, maxv );
342 }
343 // ============================================================================
345  return column_( this, m_ints, name, value );
346 }
347 // ============================================================================
348 StatusCode Tuples::TupleObj::column( const std::string& name, int value, int minv, int maxv ) {
349  return column_( this, m_ints, name, value, minv, maxv );
350 }
351 // ============================================================================
353  return find_or_create( this, name, m_ints, minv, maxv );
354 }
355 // ============================================================================
356 StatusCode Tuples::TupleObj::column( const std::string& name, unsigned int value ) {
357  return column_( this, m_uints, name, value );
358 }
359 // ============================================================================
360 StatusCode Tuples::TupleObj::column( const std::string& name, unsigned int value, unsigned int minv,
361  unsigned int maxv ) {
362  return column_( this, m_uints, name, value, minv, maxv );
363 }
364 // ============================================================================
366  Warning( "'long' has different sizes on 32/64 bit systems. Casting '" + name + "' to 'long long'",
368  .ignore();
369  return column( name, static_cast<long long>( value ) );
370 }
371 // ============================================================================
372 StatusCode Tuples::TupleObj::column( const std::string& name, const long value, const long minv, const long maxv ) {
373  Warning( "'long' has different sizes on 32/64 bit systems. Casting '" + name + "' to 'long long'",
375  .ignore();
376  return column( name, static_cast<long long>( value ), static_cast<long long>( minv ),
377  static_cast<long long>( maxv ) );
378 }
379 // ============================================================================
380 StatusCode Tuples::TupleObj::column( const std::string& name, const unsigned long value ) {
381  Warning( "'unsigned long' has different sizes on 32/64 bit systems. Casting '" + name + "' to 'unsigned long long'",
383  .ignore();
384  return column( name, static_cast<unsigned long long>( value ) );
385 }
386 // ============================================================================
387 StatusCode Tuples::TupleObj::column( const std::string& name, const unsigned long value, const unsigned long minv,
388  const unsigned long maxv ) {
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 ), static_cast<unsigned long long>( minv ),
393  static_cast<unsigned long long>( maxv ) );
394 }
395 // ============================================================================
396 StatusCode Tuples::TupleObj::column( const std::string& name, const long long value ) {
397  return column_( this, m_longlongs, name, value );
398 }
399 // ============================================================================
400 StatusCode Tuples::TupleObj::column( const std::string& name, long long value, long long minv, long long maxv ) {
401  return column_( this, m_longlongs, name, value, minv, maxv );
402 }
403 // ============================================================================
404 StatusCode Tuples::TupleObj::column( const std::string& name, unsigned long long value ) {
405  return column_( this, m_ulonglongs, name, value );
406 }
407 // ============================================================================
408 StatusCode Tuples::TupleObj::column( const std::string& name, unsigned long long value, unsigned long long minv,
409  unsigned long long maxv ) {
410  return column_( this, m_ulonglongs, name, value, minv, maxv );
411 }
412 // ============================================================================
414  return column_( this, m_bools, name, value );
415 }
416 // ============================================================================
417 // retrieve (book on demand) array-items for ntuple
418 // ============================================================================
420  // existing array ?
421  auto found = m_farrays.find( name );
422  if ( m_farrays.end() != found ) return found->second.get();
423  return create_( this, m_farrays, name,
424  [&]( const std::string& n, FArray& i ) { return this->tuple()->addIndexedItem( n, *length, i ); } );
425 }
426 // ============================================================================
427 // retrieve (book on demand) array-items for ntuple (fixed)
428 // ============================================================================
430  // existing array ?
431  auto found = m_arraysf.find( name );
432  if ( m_arraysf.end() != found ) return found->second.get();
433  return create_( this, m_arraysf, name,
434  [&]( const std::string& n, FArray& i ) { return this->tuple()->addItem( n, rows, i ); } );
435 }
436 // ============================================================================
437 // retrieve (book on demand) matrix-items for ntuple
438 // ============================================================================
440  const Tuples::TupleObj::MIndex& cols ) {
441  // existing array ?
442  auto found = m_fmatrices.find( name );
443  if ( m_fmatrices.end() != found ) return found->second.get();
444  return create_( this, m_fmatrices, name, [&]( const std::string& n, FMatrix& i ) {
445  return this->tuple()->addIndexedItem( n, *length, cols, i );
446  } );
447 }
448 // ============================================================================
449 // retrieve (book on demand) matrix-items for ntuple (fixed)
450 // ============================================================================
452  const Tuples::TupleObj::MIndex& cols ) {
453  // existing array ?
454  auto found = m_matricesf.find( name );
455  if ( m_matricesf.end() != found ) return found->second.get();
456  return create_( this, m_matricesf, name,
457  [&]( const std::string& n, FMatrix& i ) { return this->tuple()->addItem( n, rows, cols, i ); } );
458 }
459 // ============================================================================
460 // The END
461 // ============================================================================
Int * ints(const std::string &name, int minv, int maxv)
get the column
Definition: TupleObj.cpp:352
long decrement(const std::string &object)
Definition: TupleObj.cpp:195
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:266
The category assigned to a StatusCode.
Definition: StatusCode.h:74
StatusCode column(const std::string &name, float value)
Set the value for selected tuple column.
Definition: TupleObj.cpp:302
T endl(T... args)
ErrorCodes
Tuple error codes.
Definition: TupleObj.h:101
constexpr static const auto SUCCESS
Definition: StatusCode.h:96
virtual const char * name() const =0
Name of the category.
STL namespace.
bool invalid() const
invalid pointer to tuple ?
Definition: TupleObj.h:1887
T end(T... args)
void report() const
Definition: TupleObj.cpp:199
unsigned short MIndex
Definition: TupleObj.h:255
std::string m_name
name
Definition: TupleObj.h:1942
Counter(std::string msg=" Misbalance ")
Definition: TupleObj.cpp:189
STL class.
T at(T... args)
bool addItem(std::string name, std::string type)
add the item name into the list of known items
Definition: TupleObj.h:1896
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:223
virtual std::string message(code_t code) const
Description for code within this category.
Definition: StatusCode.h:82
#define STATUSCODE_ENUM_IMPL(...)
Assign a category to the StatusCode enum declared with STATUSCODE_ENUM_DECL( ENUM )
Definition: StatusCode.h:342
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:89
static const Category & default_category() noexcept
Default Gaudi StatusCode category.
Definition: StatusCode.h:357
std::map< std::string, long > m_map
Definition: TupleObj.cpp:205
T find_first_of(T... args)
StatusCode write()
write a record to NTuple
Definition: TupleObj.cpp:239
const NTuple::Tuple * tuple() const
provide the access to underlying Gaudi N-tuple
Definition: TupleObj.h:1861
long counts(const std::string &object) const
Definition: TupleObj.cpp:197
unsigned int CLID
Class ID definition.
Definition: ClassID.h:18
virtual StatusCode Error(const std::string &msg, const StatusCode sc=StatusCode::FAILURE) const =0
bool isSuccess() const
Definition: StatusCode.h:361
Abstract base class which allows the user to interact with the actual N tuple implementation.
Definition: NTuple.h:385
virtual ~TupleObj()
Definition: TupleObj.cpp:232
FArray * fArray(const std::string &name, Int *item)
get the column
Definition: TupleObj.cpp:419
const StatusCode & ignore() const
Ignore/check StatusCode.
Definition: StatusCode.h:164
T begin(T... args)
StatusCode addItem(const std::string &name, Item< TYPE > &itm)
Add a scalar data item a N tuple.
Definition: NTuple.h:513
FMatrix * fMatrix(const std::string &name, Int *item, const MIndex &cols)
get the column
Definition: TupleObj.cpp:439
bool isFailure() const
Definition: StatusCode.h:141
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:209
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:193
unsigned long code_t
type of StatusCode value
Definition: StatusCode.h:63
General namespace for Tuple properties.
Definition: Maps.h:43
T emplace_back(T... args)