14#ifndef COMMON_SIMCONFIG_INCLUDE_SIMCONFIG_CONFIGURABLEPARAM_H_
15#define COMMON_SIMCONFIG_INCLUDE_SIMCONFIG_CONFIGURABLEPARAM_H_
28#include <unordered_map>
30#include <boost/property_tree/ptree_fwd.hpp>
100 std::vector<std::pair<std::string, int>>
vvalues;
129 void add(
const std::string&
key,
const TDataMember* dm);
133 return entries.count(
key) > 0;
140 auto iter = entries.find(
key);
141 return iter != entries.end() ? &iter->second :
nullptr;
145 std::unordered_map<std::string, EnumLegalValues> entries;
149concept Container = !std::is_same_v<std::remove_cvref_t<T>, std::string> &&
requires(T
t) {
150 typename T::value_type;
151 typename T::iterator;
152 {
t.begin() } -> std::same_as<typename T::iterator>;
153 {
t.end() } -> std::same_as<typename T::iterator>;
158 typename T::key_type;
159 typename T::mapped_type;
171 template <
typename T>
175 return parseMap<T>(
str);
182 return parseSequence<T>(
str);
184 return parseScalar<T>(
str);
188 static std::string
trim(
const std::string&
str)
190 auto start =
str.find_first_not_of(
" \t\n\r\f\v");
191 if (
start == std::string::npos) {
194 auto end =
str.find_last_not_of(
" \t\n\r\f\v");
200 template <SequenceContainer SequenceT>
201 static SequenceT parseSequence(
const std::string&
str)
204 using ValueType =
typename SequenceT::value_type;
205 std::string cleaned =
str;
206 if (!cleaned.empty() && cleaned.front() ==
'[' && cleaned.back() ==
']') {
207 cleaned = cleaned.substr(1, cleaned.length() - 2);
209 if (cleaned.empty() || cleaned ==
"{}") {
212 if constexpr (Container<ValueType>) {
213 static_assert(AlwaysFalse<ValueType>,
"Nested containers are not supported as configurable parameters");
215 auto tokens = split(cleaned,
',');
216 for (
const auto& token : tokens) {
217 std::string trimmed =
trim(token);
218 result.insert(
result.end(), parseScalar<ValueType>(trimmed));
224 template <MapLike MapT>
225 static MapT parseMap(
const std::string&
str)
228 using KeyType =
typename MapT::key_type;
229 using ValueType =
typename MapT::mapped_type;
230 std::string cleaned =
str;
231 if (!cleaned.empty() && cleaned.front() ==
'{' && cleaned.back() ==
'}') {
232 cleaned = cleaned.substr(1, cleaned.length() - 2);
234 if (cleaned.empty()) {
237 if constexpr (Container<KeyType> || Container<ValueType>) {
238 static_assert(AlwaysFalse<MapT>,
"Nested containers are not supported as configurable parameters");
240 auto pairs = split(cleaned,
',');
241 for (
const auto& pair_str : pairs) {
242 auto kv = split(pair_str,
':');
243 if (kv.size() != 2) {
244 throw std::runtime_error(
"Invalid map syntax: " + pair_str +
". Expected 'key:value' format, got ");
246 KeyType
key = parseScalar<KeyType>(
trim(kv[0]));
253 template <
typename T>
254 static T parseScalar(
const std::string&
str)
256 if constexpr (std::is_same_v<T, std::string>) {
258 }
else if constexpr (std::is_same_v<T, bool>) {
260 std::transform(
lower.begin(),
lower.end(),
lower.begin(), [](
unsigned char c) { return static_cast<char>(std::tolower(c)); });
267 throw std::runtime_error(
"Invalid boolean value: " +
str);
268 }
else if constexpr (std::is_same_v<T, char> || std::is_same_v<T, signed char>) {
272 throw std::runtime_error(
"Failed to parse '" +
str +
"' as char type");
274 if (
value < std::numeric_limits<T>::min() ||
value > std::numeric_limits<T>::max()) {
275 throw std::runtime_error(
"Value out of range for char type: " +
str);
277 return static_cast<T>(
value);
278 }
else if constexpr (std::is_same_v<T, unsigned char>) {
282 throw std::runtime_error(
"Failed to parse '" +
str +
"' as unsigned char type");
284 if (
value > std::numeric_limits<T>::max()) {
285 throw std::runtime_error(
"Value out of range for unsigned char type: " +
str);
287 return static_cast<T>(
value);
288 }
else if constexpr (std::is_integral_v<T> && std::is_unsigned_v<T>) {
289 if (!
str.empty() &&
str.front() ==
'-') {
290 throw std::runtime_error(
"Value out of range for unsigned integer type: " +
str);
294 if (
pos !=
str.size() ||
value > std::numeric_limits<T>::max()) {
295 throw std::runtime_error(
"Failed to parse '" +
str +
"' as unsigned integer type");
297 return static_cast<T>(
value);
298 }
else if constexpr (std::is_integral_v<T>) {
301 if (
pos !=
str.size() ||
value < std::numeric_limits<T>::min() ||
value > std::numeric_limits<T>::max()) {
302 throw std::runtime_error(
"Failed to parse '" +
str +
"' as signed integer type");
304 return static_cast<T>(
value);
305 }
else if constexpr (std::is_floating_point_v<T>) {
309 throw std::runtime_error(
"Failed to parse '" +
str +
"' as floating point type");
311 return static_cast<T>(
value);
313 std::istringstream iss(
str);
317 if (iss.fail() || !iss.eof()) {
318 throw std::runtime_error(
"Failed to parse '" +
str +
"' as " +
typeid(T).
name());
325 static std::vector<std::string> split(
const std::string&
str,
char delimiter)
327 std::vector<std::string> tokens;
329 int bracket_depth = 0;
334 }
else if (
c ==
']') {
336 }
else if (
c ==
'{') {
338 }
else if (
c ==
'}') {
340 }
else if (
c == delimiter && bracket_depth == 0 && brace_depth == 0) {
345 tokens.push_back(current);
351 tokens.push_back(current);
374 static std::array<std::string, 3> names = {
"CODE",
"CCDB",
"RT"};
375 return names[(int)p];
382 virtual void printKeyValues(
bool showprov =
true,
bool useLogger =
false,
bool withPadding =
false,
bool showHash =
false)
const = 0;
403 static void writeJSON(std::string
const&
filename, std::string
const& keyOnly =
"");
405 static void writeINI(std::string
const&
filename, std::string
const& keyOnly =
"");
408 static void write(std::string
const&
filename, std::string
const& keyOnly =
"");
410 static std::string
asJSON(std::string
const& keyOnly =
"");
413 template <
typename T>
416 return [](
auto*
tree,
const std::string&
key) -> T {
417 if (!sIsFullyInitialized) {
420 return tree->template get<T>(
key);
424 template <
typename T>
425 static void setValue(std::string
const& mainkey, std::string
const& subkey, T
x)
427 if (!sIsFullyInitialized) {
430 return [&subkey, &
x, &mainkey](
auto*
tree) ->
void {
433 auto key = mainkey +
"." + subkey;
434 if (
tree->template get_optional<std::string>(
key).is_initialized()) {
441 }
catch (std::exception
const&
e) {
442 std::cerr <<
"Error in setValue (T) " <<
e.what() <<
"\n";
449 if (!sIsFullyInitialized) {
450 std::cerr <<
"setProvenance was called on non-initialized ConfigurableParam\n";
454 auto key = mainkey +
"." + subkey;
459 }
catch (std::exception
const&
e) {
460 std::cerr <<
"Error in setProvenance (T) " <<
e.what() <<
"\n";
466 static void setValue(std::string
const&
key, std::string
const& valuestring);
467 static void setEnumValue(
const std::string&,
const std::string&);
468 static void setArrayValue(
const std::string&,
const std::string&);
478 static void setValues(std::vector<std::pair<std::string, std::string>>
const& keyValues);
497 static void updateFromFile(std::string
const&, std::string
const& paramsList =
"",
bool unchangedOnly =
false);
500 static void updateFromJSONString(std::string
const&, std::string
const& paramsList =
"",
bool unchangedOnly =
false);
521 virtual void output(std::ostream& out)
const = 0;
545 static std::vector<ConfigurableParam*>* sRegisteredParamClasses;
547 static boost::property_tree::ptree* sPtree;
548 static bool sIsFullyInitialized;
549 static bool sRegisterMode;
556#define O2ParamDef(classname, key) \
558 classname(TRootIOCtor*) {} \
559 classname(classname const&) = delete; \
562 static constexpr char const* const sKey = key; \
563 static classname sInstance; \
564 classname() = default; \
565 template <typename T> \
566 friend class o2::conf::ConfigurableParamHelper; \
567 template <typename T, typename P> \
568 friend class o2::conf::ConfigurableParamPromoter;
571#define O2ParamImpl(classname) classname classname::sInstance;
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 e
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 d
friend std::ostream & operator<<(std::ostream &out, const ConfigurableParam &me)
virtual ~ConfigurableParam()=default
virtual void printKeyValues(bool showprov=true, bool useLogger=false, bool withPadding=false, bool showHash=false) const =0
static EParamUpdateStatus updateThroughStorageMapWithConversion(std::string const &, std::string const &)
static std::string registeredContainerAsString(const std::string &typeName, const void *source)
virtual void serializeTo(TFile *) const =0
virtual std::string getName() const =0
static void setEnumValue(const std::string &, const std::string &)
static void writeINI(std::string const &filename, std::string const &keyOnly="")
static void setValues(std::vector< std::pair< std::string, std::string > > const &keyValues)
static bool configFileExists(std::string const &filepath)
virtual void putKeyValues(boost::property_tree::ptree *)=0
static std::map< std::string, std::pair< std::type_info const &, void * > > * sKeyToStorageMap
static void printAllRegisteredParamNames()
static bool areRegisteredContainersEqual(const std::string &typeName, const void *lhs, const void *rhs)
static void setProvenance(std::string const &mainkey, std::string const &subkey, EParamProvenance p)
void setRegisterMode(bool b)
static void registerContainerType(const std::string &key, const std::string &typeName)
static std::string asJSON(std::string const &keyOnly="")
bool isInitialized() const
static void updateFromFile(std::string const &, std::string const ¶msList="", bool unchangedOnly=false)
static void write(std::string const &filename, std::string const &keyOnly="")
static bool isRegisteredContainerType(const std::string &typeName)
static T getValueAs(std::string key)
static bool assignRegisteredContainer(const std::string &typeName, void *target, const void *source)
virtual size_t getHash() const =0
virtual void initFrom(TFile *)=0
virtual EParamProvenance getMemberProvenance(const std::string &key) const =0
static void setArrayValue(const std::string &, const std::string &)
static void initPropertyTree()
static void setValue(std::string const &mainkey, std::string const &subkey, T x)
static std::string sOutputDir
static std::map< std::string, ConfigurableParam::EParamProvenance > * sValueProvenanceMap
static EParamProvenance getProvenance(const std::string &key)
static const std::string & getOutputDir()
static void printAllKeyValuePairs(bool useLogger=false)
static void toCCDB(std::string filename)
static void writeJSON(std::string const &filename, std::string const &keyOnly="")
static void setOutputDir(const std::string &d)
static std::string toString(EParamProvenance p)
static EParamUpdateStatus updateThroughStorageMap(std::string, std::string, std::type_info const &, void *)
static void setContainerValue(const std::string &, const std::string &)
static void updateFromJSONString(std::string const &, std::string const ¶msList="", bool unchangedOnly=false)
static EnumRegistry * sEnumRegistry
virtual void output(std::ostream &out) const =0
static std::string getRegisteredContainerType(const std::string &key)
virtual void syncCCDBandRegistry(void *obj)=0
static void fromCCDB(std::string filename)
static void updateFromString(std::string const &)
static T parse(const std::string &str)
static std::string trim(const std::string &str)
void add(const std::string &key, const TDataMember *dm)
std::string toString() const
bool contains(const std::string &key) const
const EnumLegalValues * operator[](const std::string &key) const
GLuint const GLchar * name
GLboolean GLboolean GLboolean b
GLsizei GLsizei GLchar * source
GLsizei const GLfloat * value
constexpr bool AlwaysFalse
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
bool isLegal(int value) const
bool isLegal(const std::string &value) const
std::vector< std::pair< std::string, int > > vvalues
int getIntValue(const std::string &value) const
std::string toString() const
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))