ATLAS Offline Software
Loading...
Searching...
No Matches
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
18namespace 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 */
27template <class T0>
28BlockFillerTool<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 */
47template <class T0>
48StatusCode
49BlockFillerTool<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 */
69template <class T0>
70inline
71StatusCode
72BlockFillerTool<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 */
109template <class T0>
110StatusCode
111BlockFillerTool<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 */
128template <class T0>
129void
130BlockFillerTool<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 */
143template <class T0, class... TYPES>
144class BlockFillerTool<Types<T0, TYPES...> >
145 : public BlockFillerTool<Types<TYPES...> >
146{
147public:
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