Project
Loading...
Searching...
No Matches
RootConfigParamHelpers.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
16#include <TClass.h>
17#include <TDataMember.h>
18#include <TDataType.h>
19#include <TEnum.h>
20#include <TEnumConstant.h>
21#include <TIterator.h>
22#include <TList.h>
23#include <iostream>
24#include <sstream>
25#include <boost/property_tree/ptree.hpp>
26#include <functional>
27
28using namespace o2::framework;
29
30namespace
31{
32bool isString(TDataMember const& dm)
33{
34 return strcmp(dm.GetTrueTypeName(), "string") == 0;
35}
36
37// a generic looper of data members of a TClass; calling a callback
38// reused in various functions below
39void loopOverMembers(TClass* cl, void* obj,
40 std::function<void(TDataMember*, int, int)>&& callback)
41{
42 auto* memberlist = cl->GetListOfDataMembers();
43 for (int i = 0; i < memberlist->GetEntries(); ++i) {
44 auto* dm = (TDataMember*)memberlist->At(i);
45
46 auto isValidComplex = [dm]() {
47 auto typehash = runtime_hash(dm->GetTypeName());
48 return isString(*dm) || dm->IsEnum() || dm->IsSTLContainer() ||
49 (typehash == compile_time_hash("o2::framework::Array2D<int>")) ||
50 (typehash == compile_time_hash("o2::framework::Array2D<float>")) ||
51 (typehash == compile_time_hash("o2::framework::Array2D<double>"));
52 };
53
54 // filter out static members for now
55 if (dm->Property() & kIsStatic) {
56 continue;
57 }
58
59 if (dm->IsaPointer()) {
60 continue;
61 }
62 if (!dm->IsBasic() && !isValidComplex()) {
63 continue;
64 }
65
66 const auto dim = dm->GetArrayDim();
67 // we support very simple vectored data in 1D for now
68 if (dim > 1) {
69 continue;
70 }
71
72 const auto size = (dim == 1) ? dm->GetMaxIndex(dim - 1) : 1; // size of array (1 if scalar)
73 for (int index = 0; index < size; ++index) {
74 callback(dm, index, size);
75 }
76 }
77}
78
79// construct name (in dependence on vector or scalar data and index)
80std::string getName(const TDataMember* dm, int index, int size)
81{
82 std::stringstream namestream;
83 namestream << dm->GetName();
84 if (size > 1) {
85 namestream << "[" << index << "]";
86 }
87 return namestream.str();
88}
89
90void ptreeToMember(boost::property_tree::ptree const& value,
91 char const* tname,
92 TDataMember* dm,
93 void* ptr)
94{
95 auto typehash = runtime_hash(dm->GetTypeName());
96 if (dm->IsSTLContainer()) {
97 switch (typehash) {
98 case compile_time_hash("vector<int>"):
99 *static_cast<std::vector<int>*>(ptr) = vectorFromBranch<int>(value);
100 return;
101 case compile_time_hash("vector<float>"):
102 *static_cast<std::vector<float>*>(ptr) = vectorFromBranch<float>(value);
103 return;
104 case compile_time_hash("vector<double>"):
105 *static_cast<std::vector<double>*>(ptr) = vectorFromBranch<double>(value);
106 return;
107 case compile_time_hash("vector<bool>"):
108 throw std::runtime_error("Bool arrays are not implemented yet");
109 case compile_time_hash("vector<std::string>"):
110 case compile_time_hash("vector<string>"):
111 *static_cast<std::vector<std::string>*>(ptr) = vectorFromBranch<std::string>(value);
112 return;
113 default:
114 throw std::runtime_error("Not an int/float/double/bool vector");
115 }
116 } else {
117 switch (typehash) {
118 case compile_time_hash("o2::framework::Array2D<int>"):
119 *static_cast<Array2D<int>*>(ptr) = array2DFromBranch<int>(value);
120 return;
121 case compile_time_hash("o2::framework::Array2D<float>"):
122 *static_cast<Array2D<float>*>(ptr) = array2DFromBranch<float>(value);
123 return;
124 case compile_time_hash("o2::framework::Array2D<double>"):
125 *static_cast<Array2D<double>*>(ptr) = array2DFromBranch<double>(value);
126 return;
127 }
128 }
129 auto* dt = dm->GetDataType();
130 if (dt != nullptr) {
131 switch (dt->GetType()) {
132 case kChar_t: {
133 *(char*)ptr = value.get_value<char>();
134 return;
135 }
136 case kUChar_t: {
137 *(unsigned char*)ptr = value.get_value<unsigned char>();
138 return;
139 }
140 case kShort_t: {
141 *(short*)ptr = value.get_value<short>();
142 return;
143 }
144 case kUShort_t: {
145 *(unsigned short*)ptr = value.get_value<unsigned short>();
146 return;
147 }
148 case kInt_t: {
149 *(int*)ptr = value.get_value<int>();
150 return;
151 }
152 case kUInt_t: {
153 *(unsigned int*)ptr = value.get_value<unsigned int>();
154 return;
155 }
156 case kLong_t: {
157 *(long*)ptr = value.get_value<long>();
158 return;
159 }
160 case kULong_t: {
161 *(unsigned long*)ptr = value.get_value<unsigned long>();
162 return;
163 }
164 case kFloat_t: {
165 *(float*)ptr = value.get_value<float>();
166 return;
167 }
168 case kDouble_t:
169 case kDouble32_t: {
170 *(double*)ptr = value.get_value<double>();
171 return;
172 }
173 case kBool_t: {
174 *(bool*)ptr = value.get_value<bool>();
175 return;
176 }
177 case kLong64_t: {
178 *(int64_t*)ptr = value.get_value<int64_t>();
179 return;
180 }
181 case kULong64_t: {
182 *(uint64_t*)ptr = value.get_value<uint64_t>();
183 return;
184 }
185 default: {
186 break;
187 }
188 }
189 }
190 // if we get here none of the above worked
191 if (strcmp(tname, "string") == 0 || strcmp(tname, "std::string") == 0) {
192 *(std::string*)ptr = value.get_value<std::string>();
193 }
194 throw std::runtime_error("Unable to override value");
195}
196
197// Convert a DataMember to a ConfigParamSpec
198ConfigParamSpec memberToConfigParamSpec(const char* tname, TDataMember* dm, void* ptr)
199{
200 auto typehash = runtime_hash(dm->GetTypeName());
201 if (dm->IsSTLContainer()) {
202 switch (typehash) {
203 case compile_time_hash("vector<int>"):
204 return ConfigParamSpec{tname, VariantType::ArrayInt, *static_cast<std::vector<int>*>(ptr), {"No help"}};
205 case compile_time_hash("vector<float>"):
206 return ConfigParamSpec{tname, VariantType::ArrayFloat, *static_cast<std::vector<float>*>(ptr), {"No help"}};
207 case compile_time_hash("vector<double>"):
208 return ConfigParamSpec{tname, VariantType::ArrayDouble, *static_cast<std::vector<double>*>(ptr), {"No help"}};
209 case compile_time_hash("vector<bool>"):
210 throw std::runtime_error("bool vector not supported yet");
211 // return ConfigParamSpec{tname, VariantType::ArrayBool, *static_cast<std::vector<bool>*>(ptr), {"No help"}};
212 case compile_time_hash("vector<std::string>"):
213 case compile_time_hash("vector<string>"):
214 return ConfigParamSpec{tname, VariantType::ArrayString, *static_cast<std::vector<std::string>*>(ptr), {"No help"}};
215 default:
216 throw std::runtime_error("Not an int/float/double/bool vector");
217 }
218 } else {
219 switch (typehash) {
220 case compile_time_hash("o2::framework::Array2D<int>"):
221 return ConfigParamSpec{tname, VariantType::Array2DInt, *static_cast<Array2D<int>*>(ptr), {"No help"}};
222 case compile_time_hash("o2::framework::Array2D<float>"):
223 return ConfigParamSpec{tname, VariantType::Array2DFloat, *static_cast<Array2D<float>*>(ptr), {"No help"}};
224 case compile_time_hash("o2::framework::Array2D<double>"):
225 return ConfigParamSpec{tname, VariantType::Array2DDouble, *static_cast<Array2D<double>*>(ptr), {"No help"}};
226 }
227 }
228 auto* dt = dm->GetDataType();
229 if (dt != nullptr) {
230 switch (dt->GetType()) {
231 case kChar_t: {
232 return ConfigParamSpec{tname, VariantType::Int8, *(char*)ptr, {"No help"}};
233 }
234 case kUChar_t: {
235 return ConfigParamSpec{tname, VariantType::UInt8, *(unsigned char*)ptr, {"No help"}};
236 }
237 case kShort_t: {
238 return ConfigParamSpec{tname, VariantType::Int16, *(short*)ptr, {"No help"}};
239 }
240 case kUShort_t: {
241 return ConfigParamSpec{tname, VariantType::UInt16, *(unsigned short*)ptr, {"No help"}};
242 }
243 case kInt_t: {
244 return ConfigParamSpec{tname, VariantType::Int, *(int*)ptr, {"No help"}};
245 }
246 case kUInt_t: {
247 return ConfigParamSpec{tname, VariantType::UInt32, *(unsigned int*)ptr, {"No help"}};
248 }
249 case kLong_t: {
250 return ConfigParamSpec{tname, VariantType::Int64, *(long*)ptr, {"No help"}};
251 }
252 case kULong_t: {
253 return ConfigParamSpec{tname, VariantType::UInt64, *(unsigned long*)ptr, {"No help"}};
254 }
255 case kFloat_t: {
256 return ConfigParamSpec{tname, VariantType::Float, *(float*)ptr, {"No help"}};
257 }
258 case kDouble_t:
259 case kDouble32_t: {
260 return ConfigParamSpec{tname, VariantType::Double, *(double*)ptr, {"No help"}};
261 }
262 case kBool_t: {
263 return ConfigParamSpec{tname, VariantType::Bool, *(bool*)ptr, {"No help"}};
264 }
265 case kLong64_t: {
266 return ConfigParamSpec{tname, VariantType::Int64, *(int64_t*)ptr, {"No help"}};
267 }
268 case kULong64_t: {
269 return ConfigParamSpec{tname, VariantType::UInt64, *(uint64_t*)ptr, {"No help"}};
270 }
271 default: {
272 break;
273 }
274 }
275 }
276 // if we get here none of the above worked
277 if (strcmp(tname, "string") == 0 || strcmp(tname, "std::string") == 0) {
278 return ConfigParamSpec{tname, VariantType::String, *(std::string*)ptr, {"No help"}};
279 }
280 throw std::runtime_error("Cannot use " + std::string(tname));
281}
282} // namespace
283
284namespace o2::framework
285{
286
287std::vector<ConfigParamSpec>
288 RootConfigParamHelpers::asConfigParamSpecsImpl(std::string const& mainKey, TClass* cl, void* obj)
289{
290 std::vector<ConfigParamSpec> specs;
291
292 auto toDataMember = [&mainKey, &specs, obj](TDataMember* dm, int index, int size) {
293 auto* dt = dm->GetDataType();
294 auto TS = dt != nullptr ? dt->Size() : 0;
295 char* ptr = ((char*)obj) + dm->GetOffset() + index * TS;
296 const std::string name = mainKey + "." + getName(dm, index, size);
297
298 specs.push_back(memberToConfigParamSpec(name.c_str(), dm, ptr));
299 };
300
301 loopOverMembers(cl, obj, toDataMember);
302 return specs;
303}
304
307void RootConfigParamHelpers::fillFromPtree(TClass* cl, void* obj, boost::property_tree::ptree const& pt)
308{
309 auto toDataMember = [obj, &pt](TDataMember* dm, int index, int size) {
310 auto* dt = dm->GetDataType();
311 auto TS = dt != nullptr ? dt->Size() : 0;
312 char* ptr = ((char*)obj) + dm->GetOffset() + index * TS;
313 const std::string name = getName(dm, index, size);
314 auto it = pt.get_child_optional(name);
315 if (!it) {
316 return;
317 }
318 ptreeToMember(*it, dm->GetTrueTypeName(), dm, ptr);
319 };
320
321 loopOverMembers(cl, obj, toDataMember);
322}
323
324} // namespace o2::framework
void loopOverMembers(TClass *cl, void *obj, std::function< void(const TDataMember *, int, int)> &&callback)
std::string getName(const TDataMember *dm, int index, int size)
bool isString(TDataMember const &dm)
int32_t i
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error First event to Number of events to Number of iterations to Number of iterations to Number of initial iterations excluded from const char Directory with events to Events directory is and not inside events Show standalone event Run event generator maximum time bin of continuous for triggered for automatic continuous for automatic continuous triggered uint64_t
configStandalone Reconstruction rec_tpc float
constexpr uint32_t runtime_hash(char const *str)
consteval uint32_t compile_time_hash(Ts... Vs)
TBranch * ptr
GLsizei const GLchar *const * string
Definition glcorearb.h:809
GLsizeiptr size
Definition glcorearb.h:659
GLuint index
Definition glcorearb.h:781
GLuint const GLchar * name
Definition glcorearb.h:781
GLsizei const GLfloat * value
Definition glcorearb.h:819
uint8_t int statusCode int
return(kp2 - aa - bb) *kp1/aa
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
RuntimeErrorRef runtime_error(const char *)
Array2D< T > array2DFromBranch(boost::property_tree::ptree const &ptree)
std::vector< T > vectorFromBranch(boost::property_tree::ptree const &branch)
std::vector< T, fair::mq::pmr::polymorphic_allocator< T > > vector
static std::vector< ConfigParamSpec > asConfigParamSpecsImpl(std::string const &mainkey, TClass *cl, void *obj)
static void fillFromPtree(TClass *cl, void *obj, boost::property_tree::ptree const &pt)