ATLAS Offline Software
BlockFillerToolMulti.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 /**
5  * @file D3PDMakerUtils/BlockFillerToolMulti.icc
6  * @author scott snyder <snyder@bnl.gov>
7  * @date Nov, 2011
8  * @brief A specialization of BlockFillerTool that can accept one
9  * of several types.
10  */
11 
12 
13 //**************************************************************************
14 // Single-argument specialization
15 //
16 
17 
18 namespace D3PD {
19 
20 
21 /**
22  * @brief Standard Gaudi tool constructor.
23  * @param type The name of the tool type.
24  * @param name The tool name.
25  * @param parent The tool's Gaudi parent.
26  */
27 template <class T0>
28 BlockFillerTool<Types<T0> >::BlockFillerTool
29  (const std::string& type,
30  const std::string& name,
31  const IInterface* parent)
32  : BlockFillerToolImpl (type, name, parent),
33  m_which (0)
34 {
35  // cppcheck-suppress missingReturn; false positive
36 }
37 
38 
39 /**
40  * @brief Configure during initialization: type-check.
41  * @param tree Our parent for tuple making.
42  * @param ti Gives the type of the object being passed to @c fillUntyped.
43  *
44  * @c configureD3PD should check that the type of the object coming as input
45  * is compatible with what it expects, and raise an error otherwise.
46  */
47 template <class T0>
48 StatusCode
49 BlockFillerTool<Types<T0> >::configureD3PD
50  (IAddVariable* tree,
51  const std::type_info& ti)
52 {
53  std::vector<const std::type_info*> tis;
54  push_ti (tis);
55  return this->configureImpl (tree, ti, tis, m_which);
56 }
57 
58 
59 /**
60  * @brief Helper to decide which which @c fill method to call.
61  *
62  * This either calls @c fill / @c fillAgain using the last type
63  * in our template argument list, or chains to the base class.
64  *
65  * It's virtual so that we can call the most-derived one from
66  * @c fillUntyped in the base class, but we also declare it as inline
67  * so that the base class chaining can be inlined.
68  */
69 template <class T0>
70 inline
71 StatusCode
72 BlockFillerTool<Types<T0> >::doFillUntyped (const void* p, bool again, size_t count)
73 {
74  if (m_which == count) {
75  if (again)
76  return this->fillAgain (*reinterpret_cast<const T0*> (p));
77  return this->fill (*reinterpret_cast<const T0*> (p));
78  }
79  std::abort();
80 }
81 
82 
83 /**
84  * @brief Fill one block.
85  * @param p The input object.
86  * @param again Set if this is a subsequent call requested by an AGAIN return
87  *
88  * This is called once per object. The type of the object at which @c p
89  * points is given by the @c ti argument to @c configureD3PD. The caller
90  * is responsible for arranging that all the pointers for booked variables
91  * are set appropriately upon entry.
92  *
93  * If the return status is the special code @c AGAIN (defined above),
94  * then this filler tool wants to make multiple entries.
95  * The parent should set up to capture a new `row' and run
96  * through the list of block filler
97  * tools again, but for this tool call @c fillAgainUntyped
98  * instead of @c fillUntyped. This should be repeated as long
99  * as @c fillAgainUntyped returns @c AGAIN.
100  *
101  * Once @c fillUntyped returns @c AGAIN, the parent should
102  * call @c fillUntyped with the same @a p argument and @c again
103  * set to @c true. This continues until @c fillUntyped returns something
104  * other than @c AGAIN.
105  *
106  * Not all parents may support this. In that case, returning
107  * @c AGAIN will be treated as an error.
108  */
109 template <class T0>
110 StatusCode
111 BlockFillerTool<Types<T0> >::fillUntyped (const void* p, bool again /*= false*/)
112 {
113  if (!p) return StatusCode::SUCCESS;
114  StatusCode stat = convert (p);
115  if (stat.isFailure())
116  return stat;
117  return doFillUntyped (p, again, 0);
118 }
119 
120 
121 /**
122  * @brief Helper to collect the list of @c type_info's that we accept.
123  *
124  * This first chains to the base class to pick up its list.
125  * Then we add the @c type_info corresponding to the last type
126  * in the template argument list.
127  */
128 template <class T0>
129 void
130 BlockFillerTool<Types<T0> >::push_ti (std::vector<const std::type_info*>& tis)
131 {
132  tis.reserve (1);
133  tis.push_back (&typeid(T0));
134 }
135 
136 
137 /**
138  * @brief A specialization of BlockFillerTool that can accept one
139  * of several types.
140  *
141  * This specialization is for the case of more than one argument.
142  */
143 template <class T0, class... TYPES>
144 class BlockFillerTool<Types<T0, TYPES...> >
145  : public BlockFillerTool<Types<TYPES...> >
146 {
147 public:
148  using Base = BlockFillerTool<Types<TYPES...> >;
149 
150  using Base::Base;
151 
152  virtual void push_ti (std::vector<const std::type_info*>& tis) override
153  {
154  tis.reserve (1 + sizeof... (TYPES));
155  tis.push_back (&typeid(T0));
156  Base::push_ti (tis);
157  }
158 
159  using Base::fill;
160  virtual StatusCode fill (const T0& /*p*/) = 0;
161 
162  using Base::fillAgain;
163  virtual StatusCode fillAgain (const T0& p) { return this->fill(p); }
164 
165  virtual StatusCode doFillUntyped (const void* p, bool again, size_t count) override
166  {
167  if (this->m_which == count) {
168  if (again)
169  return this->fillAgain (*reinterpret_cast<const T0*> (p));
170  return this->fill (*reinterpret_cast<const T0*> (p));
171  }
172  return Base::doFillUntyped (p, again, count+1);
173  }
174 };
175 
176 
177 } // namespace D3PD
178