Project
Loading...
Searching...
No Matches
ConfigurableParamHelper.h
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
12// first version 8/2018, Sandro Wenzel
13
14#ifndef COMMON_SIMCONFIG_INCLUDE_SIMCONFIG_CONFIGURABLEPARAMHELPER_H_
15#define COMMON_SIMCONFIG_INCLUDE_SIMCONFIG_CONFIGURABLEPARAMHELPER_H_
16
18
19#include <algorithm>
20#include <memory>
21#include <numeric>
22#include <string_view>
23#include <TClass.h>
24#include <TFile.h>
25#include <TDataMember.h>
26#include <type_traits>
27#include <typeinfo>
28#include <utility>
29
30namespace o2::conf
31{
32
33// ----------------------------------------------------------------
34
35inline std::size_t damerauLevenshteinDistance(std::string_view a, std::string_view b)
36{
37 const std::size_t n = a.size();
38 const std::size_t m = b.size();
39 if (n == 0) {
40 return m;
41 }
42 if (m == 0) {
43 return n;
44 }
45 std::vector<std::size_t> prev(m + 1), curr(m + 1), prev2(m + 1);
46 std::iota(prev.begin(), prev.end(), 0);
47 for (std::size_t i = 1; i <= n; ++i) {
48 curr[0] = i;
49 for (std::size_t j = 1; j <= m; ++j) {
50 std::size_t cost = (a[i - 1] == b[j - 1]) ? 0 : 1;
51 curr[j] = std::min({prev[j] + 1,
52 curr[j - 1] + 1,
53 prev[j - 1] + cost});
54 if (i > 1 && j > 1 && a[i - 1] == b[j - 2] &&
55 a[i - 2] == b[j - 1]) {
56 curr[j] = std::min(curr[j], prev2[j - 2] + 1);
57 }
58 }
59 prev2 = std::move(prev);
60 prev = std::move(curr);
61 curr.assign(m + 1, 0);
62 }
63 return prev[m];
64}
65
66// ----------------------------------------------------------------
67
68// Utility structure for passing around ConfigurableParam data member info
69// (where value is the string representation)
71 std::string name;
72 std::string value;
73 std::string provenance;
74
75 std::string toString(std::string const& prefix, bool showProv, size_t padding = 0) const;
76};
77
78// ----------------------------------------------------------------
79
80// just a (non-templated) helper with exclusively private functions
81// used by ConfigurableParamHelper
83{
84 private:
85 static std::vector<ParamDataMember>* getDataMembersImpl(std::string const& mainkey, TClass* cl, void*,
86 std::map<std::string, ConfigurableParam::EParamProvenance> const* provmap, size_t virtualoffset);
87
88 static void fillKeyValuesImpl(std::string const& mainkey, TClass* cl, void*, boost::property_tree::ptree*,
89 std::map<std::string, std::pair<std::type_info const&, void*>>*,
90 EnumRegistry*, size_t offset);
91
92 static void printWarning(std::type_info const&);
93
94 static void assignmentImpl(std::string const& mainkey, TClass* cl, void* to, void* from,
95 std::map<std::string, ConfigurableParam::EParamProvenance>* provmap, size_t offset);
96 static void syncCCDBandRegistry(std::string const& mainkey, TClass* cl, void* to, void* from,
97 std::map<std::string, ConfigurableParam::EParamProvenance>* provmap, size_t offset);
98
99 static void outputMembersImpl(std::ostream& out, std::string const& mainkey, std::vector<ParamDataMember> const* members, bool showProv, bool useLogger, bool withPadding = false, bool showHash = false);
100 static void printMembersImpl(std::string const& mainkey, std::vector<ParamDataMember> const* members, bool showProv, bool useLogger, bool withPadding, bool showHash);
101
102 static size_t getHashImpl(std::string const& mainkey, std::vector<ParamDataMember> const* members);
103
104 template <typename P>
106
107 template <typename Base, typename P>
109};
110
111// ----------------------------------------------------------------
112
113// implementer (and checker) for concrete ConfigurableParam classes P
114template <typename P>
116{
117 public:
119 static const P& Instance()
120 {
121 return P::sInstance;
122 }
123
124 // ----------------------------------------------------------------
125
126 std::string getName() const final
127 {
128 return P::sKey;
129 }
130
131 // ----------------------------------------------------------------
132 // get the provenace of the member with given key
133 EParamProvenance getMemberProvenance(const std::string& key) const final
134 {
135 return getProvenance(getName() + '.' + key);
136 }
137
138 // ----------------------------------------------------------------
139
140 // one of the key methods, using introspection to print itself
141 void printKeyValues(bool showProv = true, bool useLogger = false, bool withPadding = true, bool showHash = true) const final
142 {
143 if (!isInitialized()) {
144 initialize();
145 }
146 auto members = std::unique_ptr<std::vector<ParamDataMember>>(getDataMembers());
147 _ParamHelper::printMembersImpl(getName(), members.get(), showProv, useLogger, withPadding, showHash);
148 }
149
150 //
151 size_t getHash() const final
152 {
153 auto members = std::unique_ptr<std::vector<ParamDataMember>>(getDataMembers());
154 return _ParamHelper::getHashImpl(getName(), members.get());
155 }
156
157 // ----------------------------------------------------------------
158
159 void output(std::ostream& out) const final
160 {
161 auto members = std::unique_ptr<std::vector<ParamDataMember>>(getDataMembers());
162 _ParamHelper::outputMembersImpl(out, getName(), members.get(), true, false);
163 }
164
165 // ----------------------------------------------------------------
166
167 // Grab the list of ConfigurableParam data members
168 // Returns a nullptr if the TClass of the P template class cannot be created.
169 std::vector<ParamDataMember>* getDataMembers() const
170 {
171 // just a helper line to make sure P::sInstance is looked-up
172 // and that compiler complains about missing static sInstance of type P
173 // volatile void* ptr = (void*)&P::sInstance;
174 // static assert on type of sInstance:
175 static_assert(std::is_same<decltype(P::sInstance), P>::value,
176 "static instance must of same type as class");
177
178 // obtain the TClass for P and delegate further
179 auto cl = TClass::GetClass(typeid(P));
180 if (!cl) {
181 _ParamHelper::printWarning(typeid(P));
182 return nullptr;
183 }
184
185 return _ParamHelper::getDataMembersImpl(getName(), cl, (void*)this, sValueProvenanceMap, 0);
186 }
187
188 // ----------------------------------------------------------------
189
190 // fills the data structures with the initial default values
191 void putKeyValues(boost::property_tree::ptree* tree) final
192 {
193 auto cl = TClass::GetClass(typeid(P));
194 if (!cl) {
195 _ParamHelper::printWarning(typeid(P));
196 return;
197 }
198 _ParamHelper::fillKeyValuesImpl(getName(), cl, (void*)this, tree, sKeyToStorageMap, sEnumRegistry, 0);
199 }
200
201 // ----------------------------------------------------------------
202
203 void initFrom(TFile* file) final
204 {
205 // switch off auto registering since the readback object is
206 // only a "temporary" singleton
207 setRegisterMode(false);
208 P* readback = nullptr;
209 file->GetObject(getName().c_str(), readback);
210 if (readback != nullptr) {
211 _ParamHelper::assignmentImpl(getName(), TClass::GetClass(typeid(P)), (void*)this, (void*)readback,
213 delete readback;
214 }
215 setRegisterMode(true);
216 }
217
218 // ----------------------------------------------------------------
219
220 void syncCCDBandRegistry(void* externalobj) final
221 {
222 // We may be getting an external copy from CCDB which is passed as externalobj.
223 // The task of this function is to
224 // a) update the internal registry with fields coming from CCDB
225 // but only if keys have not been modified via RT == command line / ini file
226 // b) update the external object with with fields having RT provenance
227 //
228 setRegisterMode(false);
229 _ParamHelper::syncCCDBandRegistry(getName(), TClass::GetClass(typeid(P)), (void*)this, (void*)externalobj,
231 setRegisterMode(true);
232 }
233
234 // ----------------------------------------------------------------
235
236 void serializeTo(TFile* file) const final
237 {
238 file->WriteObjectAny((void*)this, TClass::GetClass(typeid(P)), getName().c_str());
239 }
240};
241
242// Promotes a simple struct Base to a configurable parameter class
243// Aka implements all interfaces for a ConfigurableParam P, which shares or
244// takes the fields from a Base struct
245template <typename P, typename Base>
247{
248 public:
250
251 static const P& Instance()
252 {
253 return P::sInstance;
254 }
255
256 // extracts a copy of the underlying data struct
257 Base detach() const
258 {
259 static_assert(std::copyable<Base>, "Base type must be copyable.");
260 return static_cast<Base>(*this);
261 }
262
263 // ----------------------------------------------------------------
264 std::string getName() const final
265 {
266 return P::sKey;
267 }
268
269 // ----------------------------------------------------------------
270 // get the provenace of the member with given key
271 EParamProvenance getMemberProvenance(const std::string& key) const final
272 {
273 return getProvenance(getName() + '.' + key);
274 }
275
276 // ----------------------------------------------------------------
277
278 // one of the key methods, using introspection to print itself
279 void printKeyValues(bool showProv = true, bool useLogger = false, bool withPadding = true, bool showHash = true) const final
280 {
281 if (!isInitialized()) {
282 initialize();
283 }
284 auto members = std::unique_ptr<std::vector<ParamDataMember>>(getDataMembers());
285 _ParamHelper::printMembersImpl(getName(), members.get(), showProv, useLogger, withPadding, showHash);
286 }
287
288 //
289 size_t getHash() const final
290 {
291 auto members = std::unique_ptr<std::vector<ParamDataMember>>(getDataMembers());
292 return _ParamHelper::getHashImpl(getName(), members.get());
293 }
294
295 // ----------------------------------------------------------------
296
297 void output(std::ostream& out) const final
298 {
299 auto members = std::unique_ptr<std::vector<ParamDataMember>>(getDataMembers());
300 _ParamHelper::outputMembersImpl(out, getName(), members.get(), true, false);
301 }
302
303 // ----------------------------------------------------------------
304
305 // Grab the list of ConfigurableParam data members
306 // Returns a nullptr if the TClass of the P template class cannot be created.
307 std::vector<ParamDataMember>* getDataMembers() const
308 {
309 // just a helper line to make sure P::sInstance is looked-up
310 // and that compiler complains about missing static sInstance of type P
311 // volatile void* ptr = (void*)&P::sInstance;
312 // static assert on type of sInstance:
313 static_assert(std::is_same<decltype(P::sInstance), P>::value,
314 "static instance must of same type as class");
315
316 // obtain the TClass for the Base type and delegate further
317 auto cl = TClass::GetClass(typeid(Base));
318 if (!cl) {
319 _ParamHelper::printWarning(typeid(Base));
320 return nullptr;
321 }
322
323 // we need to put an offset of 8 bytes since internally this is using data members of the Base class
324 // which doesn't account for the virtual table of P
325 return _ParamHelper::getDataMembersImpl(getName(), cl, (void*)this, sValueProvenanceMap, 8);
326 }
327
328 // ----------------------------------------------------------------
329
330 // fills the data structures with the initial default values
331 void putKeyValues(boost::property_tree::ptree* tree) final
332 {
333 auto cl = TClass::GetClass(typeid(Base));
334 if (!cl) {
335 _ParamHelper::printWarning(typeid(Base));
336 return;
337 }
338 _ParamHelper::fillKeyValuesImpl(getName(), cl, (void*)this, tree, sKeyToStorageMap, sEnumRegistry, 8);
339 }
340
341 // ----------------------------------------------------------------
342
343 void initFrom(TFile* file) final
344 {
345 // switch off auto registering since the readback object is
346 // only a "temporary" singleton
347 setRegisterMode(false);
348 P* readback = nullptr;
349 file->GetObject(getName().c_str(), readback);
350 if (readback != nullptr) {
351 _ParamHelper::assignmentImpl(getName(), TClass::GetClass(typeid(Base)), (void*)this, (void*)readback,
353 delete readback;
354 }
355 setRegisterMode(true);
356 }
357
358 // ----------------------------------------------------------------
359
360 void syncCCDBandRegistry(void* externalobj) final
361 {
362 // We may be getting an external copy from CCDB which is passed as externalobj.
363 // The task of this function is to
364 // a) update the internal registry with fields coming from CCDB
365 // but only if keys have not been modified via RT == command line / ini file
366 // b) update the external object with with fields having RT provenance
367 //
368 setRegisterMode(false);
369 _ParamHelper::syncCCDBandRegistry(getName(), TClass::GetClass(typeid(Base)), (void*)this, (void*)externalobj,
371 setRegisterMode(true);
372 }
373
374 // ----------------------------------------------------------------
375
376 void serializeTo(TFile* file) const final
377 {
378 file->WriteObjectAny((void*)this, TClass::GetClass(typeid(P)), getName().c_str());
379 }
380};
381
382inline bool isContainer(const std::string& typeName)
383{
385}
386
387inline bool isContainer(TDataMember const& dm)
388{
389 if (auto* cl = dm.GetClass(); cl && isContainer(cl->GetName())) {
390 return true;
391 }
392 return isContainer(dm.GetTrueTypeName()) || isContainer(dm.GetFullTypeName());
393}
394
395} // namespace o2::conf
396
397#endif /* COMMON_SIMCONFIG_INCLUDE_SIMCONFIG_CONFIGURABLEPARAMHELPER_H_ */
uint16_t padding
int32_t i
bounded_vector< int > members
uint32_t j
Definition RawData.h:0
StringRef key
EParamProvenance getMemberProvenance(const std::string &key) const final
void printKeyValues(bool showProv=true, bool useLogger=false, bool withPadding=true, bool showHash=true) const final
void syncCCDBandRegistry(void *externalobj) final
void serializeTo(TFile *file) const final
void putKeyValues(boost::property_tree::ptree *tree) final
std::vector< ParamDataMember > * getDataMembers() const
void output(std::ostream &out) const final
void printKeyValues(bool showProv=true, bool useLogger=false, bool withPadding=true, bool showHash=true) const final
std::vector< ParamDataMember > * getDataMembers() const
EParamProvenance getMemberProvenance(const std::string &key) const final
void serializeTo(TFile *file) const final
void output(std::ostream &out) const final
void putKeyValues(boost::property_tree::ptree *tree) final
void syncCCDBandRegistry(void *externalobj) final
static std::map< std::string, std::pair< std::type_info const &, void * > > * sKeyToStorageMap
static bool isRegisteredContainerType(const std::string &typeName)
static std::map< std::string, ConfigurableParam::EParamProvenance > * sValueProvenanceMap
static EParamProvenance getProvenance(const std::string &key)
static EnumRegistry * sEnumRegistry
GLdouble n
Definition glcorearb.h:1982
const GLfloat * m
Definition glcorearb.h:4066
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLintptr offset
Definition glcorearb.h:660
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
bool isContainer(const std::string &typeName)
std::size_t damerauLevenshteinDistance(std::string_view a, std::string_view b)
std::string toString(std::string const &prefix, bool showProv, size_t padding=0) const
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))