Project
Loading...
Searching...
No Matches
ConfigParamsHelper.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#ifndef FRAMEWORK_CONFIGPARAMSHELPER_H
12#define FRAMEWORK_CONFIGPARAMSHELPER_H
13
15#include <boost/program_options.hpp>
16
17#include <string>
18#include <vector>
19#include <string>
20#include <type_traits>
21
22namespace o2::framework
23{
24
25using options_description = boost::program_options::options_description;
26
29 options_description& options,
30 const std::vector<ConfigParamSpec>& specs,
32
36 static bool dpl2BoostOptions(const std::vector<ConfigParamSpec>& spec,
37 options_description& options,
38 boost::program_options::options_description const& vetos = options_description());
39
42 static constexpr size_t MaxHelpDefaultLength = 40;
43
46 static std::string defaultValueForHelp(std::string const& value);
47
49 static bool hasOption(const std::vector<ConfigParamSpec>& specs, const std::string& optName);
50
53 static void addOptionIfMissing(std::vector<ConfigParamSpec>& specs, const ConfigParamSpec& spec);
54
56 template <typename ContainerType>
57 static boost::program_options::options_description
58 prepareOptionDescriptions(ContainerType const& workflow,
59 std::vector<ConfigParamSpec> const& currentWorkflowOptions,
61 std::string mode = "full")
62 {
63 boost::program_options::options_description toplevel;
64 boost::program_options::options_description wo("Global workflow options");
65 if (dpl2BoostOptions(currentWorkflowOptions, wo, vetos)) {
66 toplevel.add(wo);
67 }
68 std::string specOptionsDescription = "Available data processors";
69 if (mode == "short") {
70 specOptionsDescription += " (full info with '--help full')";
71 }
72 options_description specOptions(specOptionsDescription);
73 for (const auto& spec : workflow) {
74 std::string name = "Data processor options: " + spec.name;
75 boost::program_options::options_description processorOptions(name);
76 if (dpl2BoostOptions(spec.options, processorOptions, vetos)) {
77 // if vetos have been provided to the function we also need to make
78 // sure that there are no duplicate option definitions for the individual
79 // processor specs, so we add in order to be vetos for all subsequent specs.
80 // Note: this only concerns the main parser, all individual options are
81 // handled when starting individual processors.
82 if (vetos.options().size() > 0) {
83 vetos.add(processorOptions);
84 }
85 if (mode == "full") {
86 specOptions.add(processorOptions);
87 } else if (mode == spec.name) {
88 toplevel.add(processorOptions);
89 break;
90 }
91 }
92 if (mode == "full" || mode == "short") {
93 std::string help;
94 if (mode == "full") {
95 help = "Option groups by process name: --" + spec.name + R"( "<processor options>")";
96 } else if (mode == "short" && processorOptions.options().size() > 0) {
97 help = "Use '--help " + spec.name + "' to display processor options";
98 } else if (mode == "short" && processorOptions.options().size() == 0) {
99 help = "No processor options";
100 }
101 specOptions.add_options()(spec.name.c_str(),
102 boost::program_options::value<std::string>(),
103 help.c_str());
104 }
105 }
106 if (workflow.size() > 0 && (mode == "full" || mode == "short")) {
107 toplevel.add(specOptions);
108 }
109 return toplevel;
110 }
111
112 template <VariantType V>
113 static void addConfigSpecOption(const ConfigParamSpec& spec,
114 boost::program_options::options_description& options)
115 {
116 const char* name = spec.name.c_str();
117 const char* help = spec.help.c_str();
118
119 if constexpr (isSimpleVariant<V>()) {
120 using Type = typename variant_type<V>::type;
121 using BoostType = typename std::conditional<V == VariantType::String, std::string, Type>::type;
122 auto value = boost::program_options::value<BoostType>();
123 if constexpr (V == VariantType::String) {
124 auto defaultValue = spec.defaultValue.get<BoostType>();
125 value = value->default_value(defaultValue, defaultValueForHelp(defaultValue));
126 } else {
127 value = value->default_value(spec.defaultValue.get<BoostType>());
128 }
129 if constexpr (V == VariantType::Bool) {
130 // for bool values we also support the zero_token option to make
131 // the option usable as a single switch
132 value = value->zero_tokens();
133 }
134 options.add_options()(name, value, help);
135 } else if constexpr (isArray<V>() || isArray2D<V>()) {
136 auto value = boost::program_options::value<std::string>();
137 auto defaultValue = spec.defaultValue.asString();
138 value = value->default_value(defaultValue, defaultValueForHelp(defaultValue));
139 if constexpr (V != VariantType::String) {
140 value = value->multitoken();
141 }
142 options.add_options()(name, value, help);
143 } else if constexpr (isLabeledArray<V>()) {
144 // the JSON representation is passed as a single argument
145 auto value = boost::program_options::value<std::string>();
146 auto defaultValue = spec.defaultValue.asString();
147 value = value->default_value(defaultValue, defaultValueForHelp(defaultValue));
148 options.add_options()(name, value, help);
149 } else {
150 using Type = typename variant_type<V>::type;
151 using BoostType = typename std::conditional<V == VariantType::String, std::string, Type>::type;
152 auto value = boost::program_options::value<BoostType>();
153 options.add_options()(name, value, help);
154 }
155 }
156};
157
158} // namespace o2::framework
159#endif // FRAMEWORK_CONFIGPARAMSHELPER_H
std::string asString() const
Definition Variant.cxx:87
GLenum mode
Definition glcorearb.h:266
GLuint const GLchar * name
Definition glcorearb.h:781
GLsizei const GLfloat * value
Definition glcorearb.h:819
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
boost::program_options::options_description options_description
static bool hasOption(const std::vector< ConfigParamSpec > &specs, const std::string &optName)
Check if option is defined.
static void addOptionIfMissing(std::vector< ConfigParamSpec > &specs, const ConfigParamSpec &spec)
static constexpr size_t MaxHelpDefaultLength
static void addConfigSpecOption(const ConfigParamSpec &spec, boost::program_options::options_description &options)
static boost::program_options::options_description prepareOptionDescriptions(ContainerType const &workflow, std::vector< ConfigParamSpec > const &currentWorkflowOptions, options_description vetos=options_description(), std::string mode="full")
populate boost program options for a complete workflow
static bool dpl2BoostOptions(const std::vector< ConfigParamSpec > &spec, options_description &options, boost::program_options::options_description const &vetos=options_description())
static void populateBoostProgramOptions(options_description &options, const std::vector< ConfigParamSpec > &specs, options_description vetos=options_description())
static std::string defaultValueForHelp(std::string const &value)