2 #include "cetlib/filepath_maker.h" 3 #include "cetlib/parsed_program_options.h" 15 std::string
const fhicl_env_var{
"FHICL_FILE_PATH"};
17 std::string
const help{
"Help"};
18 std::string
const processing{
"Processing"};
19 std::string
const config{
"Configuration"};
20 std::string
const usage{
"Usage error"};
27 std::string input_filename;
28 std::string atom_as{};
29 std::string sequence_of{};
31 bool allow_missing{
false};
32 std::string parameter_key{};
33 std::unique_ptr<cet::filepath_maker> policy;
34 std::string lookup_path;
37 using supported_types_t =
39 using strings_t = std::vector<std::string>;
41 std::variant<Options, Help>
42 process_arguments(
int argc,
44 supported_types_t
const& supported_types)
46 namespace bpo = boost::program_options;
50 bpo::options_description desc(
51 "Usage: fhicl-get [options] [key] <file>\n\n" 52 "Required parameters:\n" 53 " [key] A fully-qualified parameter key of the form 'a.b.c.d'.\n" 54 " When used with the --names-in program option, one may " 56 " this option to print all top-level names in the file.\n" 57 " <file> A valid FHiCL document that contains the parameter with\n" 58 " the name as specified for <key>\n\n" 62 (
"help,h",
"Produce this help message")
63 (
"atom-as", bpo::value<std::string>(&opts.atom_as),
64 "Return value for the supplied key as an atom with the provided C++ type.")
65 (
"sequence-of", bpo::value<std::string>(&opts.sequence_of),
66 "Return value for the supplied key as a sequence of the provided C++ type.")
67 (
"names-in",
"Print the top-level names of the supplied key, which " 68 "must correspond to a FHiCL table.")
70 "Return to the command line if the supplied key does not exist when using " 71 "the --names-in option.")
73 bpo::value<std::string>()->default_value(
"permissive"),
"see --supported-policies")
75 bpo::value<std::string>(&opts.lookup_path)->default_value(fhicl_env_var),
76 "path or environment variable to be used by lookup-policy")
77 (
"supported-types",
"list the C++ types supported for by the --atom-as and --sequence-of options.")
78 (
"supported-policies",
"list the supported file lookup policies");
81 bpo::options_description positional_desc;
82 auto split_args = [&opts](
auto const& args) {
83 auto const n_args =
size(args);
84 assert(n_args < 3ull);
86 opts.input_filename = args[0];
90 opts.parameter_key = args[0];
91 opts.input_filename = args[1];
96 positional_desc.add_options()
97 (
"key-conf", bpo::value<strings_t>()->composing()->notifier(split_args));
100 bpo::positional_options_description p;
101 p.add(
"key-conf", 2);
103 bpo::options_description all;
104 all.add(desc).add(positional_desc);
106 auto const vm = cet::parsed_program_options(argc, argv, all, p);
108 if (vm.count(
"help")) {
109 std::ostringstream oss;
110 oss <<
'\n' << desc <<
'\n';
111 return Help{oss.str()};
114 if (vm.count(
"supported-types")) {
115 std::string result{R
"( 116 For the following command line: 118 fhicl-get --atom-as=T <key> <file> 120 the <file> is queried for the <key>, and an attempt is made to 121 interpret the corresponding value as an object of type T. 123 If instead the command line were specified as: 125 fhicl-get --sequence-of=T <key> <file> 127 then the value corresponding to <key> would be interpreted as an 128 std::vector<T> object. 130 For either the --atom-as or --sequence-of program options, an 131 exception will be thrown if the <key> parameter does not exist in the 132 <file>, or if the parameter does not correspond to a value that can be 133 interpreted according to the user-specified command-line. 136 result += supported_types.help_message(); 141 cet::lookup_policy_selector
const supported_policies{};
142 if (vm.count(
"supported-policies")) {
143 return Help{supported_policies.help_message()};
146 if (
empty(opts.input_filename)) {
147 std::ostringstream err_stream;
148 err_stream <<
"\nMissing input configuration file.\n\n" << desc <<
'\n';
152 opts.names_in = vm.count(
"names-in") == 1;
153 auto const options_count = vm.count(
"atom-as") + vm.count(
"sequence-of") +
154 static_cast<unsigned>(opts.names_in);
156 if (options_count == 0) {
158 <<
"One of the 'atom-as', 'sequence-of', and 'names-in' program " 159 "options must be specified.\n";
161 if (options_count > 1) {
163 <<
"The 'atom-as', 'sequence-of', and 'names-in' program options " 164 "are mutually exclusive and may only appear once in the command " 168 if (not opts.names_in and
empty(opts.parameter_key)) {
170 <<
"A key must be specified unless the '--names-in' option is used.\n";
173 opts.allow_missing = vm.count(
"allow-missing");
174 if (opts.allow_missing) {
175 if (not opts.names_in) {
177 <<
"The 'allow-missing' program option may be used only with the " 178 "'names-in' option.\n";
180 if (
empty(opts.parameter_key)) {
182 <<
"The 'allow-missing' program option may be used only when a " 183 "fully-qualified key is also specified.\n";
187 supported_policies.select(vm[
"lookup-policy"].as<std::string>(),
188 vm[
"lookup-path"].as<std::string>());
196 for (
auto const& name : names) {
197 std::cout << name <<
'\n';
203 std::string
const& key,
204 bool const allow_missing)
217 <<
"A parameter with the fully-qualified key '" << key
218 <<
"' does not exist.";
223 <<
"' does not have a table value.";
233 supported_types_t
const printer_for_types{};
234 auto const maybe_opts = process_arguments(argc, argv, printer_for_types);
236 if (std::holds_alternative<Help>(maybe_opts)) {
237 std::cout << std::get<Help>(maybe_opts).msg;
241 auto const& opts = std::get<Options>(maybe_opts);
246 auto const& key = opts.parameter_key;
249 print_table_names(pset, key, opts.allow_missing);
253 if (not pset.has_key(key)) {
254 throw cet::exception{config} <<
"A parameter with the fully-qualified key '" 255 << key <<
"' does not exist.";
258 if (not
empty(opts.atom_as)) {
259 printer_for_types.value_for_atom(pset, opts.atom_as, key);
263 if (not
empty(opts.sequence_of)) {
264 printer_for_types.value_for_sequence(pset, opts.sequence_of, key);
271 std::cerr << e.what();
static ParameterSet make(intermediate_table const &tbl)
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
bool is_key_to_table(std::string const &key) const
T get(std::string const &key) const
int fhicl_get_impl(int argc, char **argv)
bool has_key(std::string const &key) const
std::vector< std::string > get_names() const
cet::coded_exception< error, detail::translate > exception
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.