Goby3  3.1.4
2024.02.22
configuration_reader.h
Go to the documentation of this file.
1 // Copyright 2012-2024:
2 // GobySoft, LLC (2013-)
3 // Massachusetts Institute of Technology (2007-2014)
4 // Community contributors (see AUTHORS file)
5 // File authors:
6 // Toby Schneider <toby@gobysoft.org>
7 //
8 //
9 // This file is part of the Goby Underwater Autonomy Project Libraries
10 // ("The Goby Libraries").
11 //
12 // The Goby Libraries are free software: you can redistribute them and/or modify
13 // them under the terms of the GNU Lesser General Public License as published by
14 // the Free Software Foundation, either version 2.1 of the License, or
15 // (at your option) any later version.
16 //
17 // The Goby Libraries are distributed in the hope that they will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // GNU Lesser General Public License for more details.
21 //
22 // You should have received a copy of the GNU Lesser General Public License
23 // along with Goby. If not, see <http://www.gnu.org/licenses/>.
24 
25 #ifndef GOBY_MIDDLEWARE_APPLICATION_CONFIGURATION_READER_H
26 #define GOBY_MIDDLEWARE_APPLICATION_CONFIGURATION_READER_H
27 
28 #include <fstream> // for ostream
29 #include <string> // for string
30 #include <vector> // for vector
31 
32 #include <boost/lexical_cast/bad_lexical_cast.hpp> // for bad_lexical...
33 #include <boost/program_options/options_description.hpp> // for options_des...
34 #include <boost/program_options/value_semantic.hpp> // for value, bool...
35 #include <boost/program_options/variables_map.hpp> // for variable_va...
36 #include <google/protobuf/descriptor.h> // for FieldDescri...
37 
38 #include "goby/exception.h" // for Exception
39 #include "goby/protobuf/option_extensions.pb.h" // for GobyFieldOpt...
40 #include "goby/util/as.h" // for as
41 
42 namespace google
43 {
44 namespace protobuf
45 {
46 class Message;
47 } // namespace protobuf
48 } // namespace google
49 
50 namespace goby
51 {
52 namespace middleware
53 {
56 class ConfigException : public Exception
57 {
58  public:
59  ConfigException(const std::string& s) : Exception(s) {}
60 
61  private:
62 };
63 
67 {
68  public:
79  static int read_cfg(int argc, char* argv[], google::protobuf::Message* message,
80  std::string* application_name, std::string* binary_name,
81  boost::program_options::options_description* od_all,
82  boost::program_options::variables_map* var_map,
83  bool check_required_configuration = true);
84 
89  static void check_required_cfg(const google::protobuf::Message& message,
90  const std::string& binary);
91 
92  static void get_protobuf_program_options(
94  boost::program_options::options_description>& od_map,
95  const google::protobuf::Descriptor* desc,
96  std::map<std::string, std::string>& environmental_var_map);
97 
99  {
100  std::string name;
101  bool required;
102  int position_max_count; // -1 is infinity
103  };
104 
105  static void get_positional_options(const google::protobuf::Descriptor* desc,
106  // position -> required -> name
107  std::vector<PositionalOption>& positional_options);
108 
109  static void set_protobuf_program_option(const boost::program_options::variables_map& vm,
110  google::protobuf::Message& message,
111  const std::string& full_name,
112  const boost::program_options::variable_value& value,
113  bool overwrite_if_exists);
114 
115  static void
116  get_example_cfg_file(google::protobuf::Message* message, std::ostream* human_desc_ss,
117  const std::string& indent = "",
120 
121  private:
122  enum
123  {
124  MAX_CHAR_PER_LINE = 66
125  };
126  enum
127  {
128  MIN_CHAR = 20
129  };
130 
131  static void
132  build_description(const google::protobuf::Descriptor* desc, std::ostream& human_desc,
133  const std::string& indent = "", bool use_color = true,
136 
137  static void
138  build_description_field(const google::protobuf::FieldDescriptor* desc, std::ostream& human_desc,
139  const std::string& indent, bool use_color,
141 
142  static void wrap_description(std::string* description, int num_blanks);
143 
144  static std::string label(const google::protobuf::FieldDescriptor* field_desc);
145 
146  static std::string word_wrap(std::string s, unsigned width, const std::string& delim);
147 
148  template <typename T>
149  static void set_single_option(boost::program_options::options_description& po_desc,
150  const google::protobuf::FieldDescriptor* field_desc,
151  const T& default_value, const std::string& name,
152  const std::string& description)
153  {
154  if (!field_desc->is_repeated())
155  {
156  if (field_desc->has_default_value())
157  {
158  po_desc.add_options()(
159  name.c_str(), boost::program_options::value<T>()->default_value(default_value),
160  description.c_str());
161  }
162  else
163  {
164  po_desc.add_options()(name.c_str(), boost::program_options::value<T>(),
165  description.c_str());
166  }
167  }
168  else
169  {
170  if (field_desc->has_default_value())
171  {
172  po_desc.add_options()(
173  name.c_str(),
174  boost::program_options::value<std::vector<T>>()
175  ->default_value(std::vector<T>(1, default_value),
176  goby::util::as<std::string>(default_value))
177  ->composing(),
178  description.c_str());
179  }
180  else
181  {
182  po_desc.add_options()(name.c_str(),
183  boost::program_options::value<std::vector<T>>()->composing(),
184  description.c_str());
185  }
186  }
187  }
188 
189  // special case for bool presence/absence when default is false
190  // for example, for the bool field "foo", "--foo" is true and omitting "--foo" is false, rather than --foo=true/false
191  static void set_single_option(boost::program_options::options_description& po_desc,
192  const google::protobuf::FieldDescriptor* field_desc,
193  bool default_value, const std::string& name,
194  const std::string& description)
195  {
196  if (!field_desc->is_repeated() && field_desc->has_default_value() && default_value == false)
197  {
198  po_desc.add_options()(
199  name.c_str(), boost::program_options::bool_switch()->default_value(default_value),
200  description.c_str());
201  }
202  else
203  {
204  set_single_option<bool>(po_desc, field_desc, default_value, name, description);
205  }
206  }
207 
208  static void write_usage(const std::string& binary,
209  const std::vector<PositionalOption>& positional_options,
210  std::ostream* out)
211  {
212  (*out) << "Usage: " << binary << " ";
213  for (const auto& po : positional_options)
214  {
215  if (!po.required)
216  (*out) << "[";
217  (*out) << "<" << po.name;
218  if (po.position_max_count > 1)
219  (*out) << "(" << po.position_max_count << ")";
220  else if (po.position_max_count == -1)
221  (*out) << "(...)";
222  (*out) << ">";
223  if (!po.required)
224  (*out) << "]";
225  (*out) << " ";
226  }
227  (*out) << "[options]\n";
228  }
229 };
230 } // namespace middleware
231 } // namespace goby
232 
233 #endif
goby::GobyFieldOptions_ConfigurationOptions_ConfigAction
GobyFieldOptions_ConfigurationOptions_ConfigAction
Definition: option_extensions.pb.h:94
goby::middleware::ConfigReader::read_cfg
static int read_cfg(int argc, char *argv[], google::protobuf::Message *message, std::string *application_name, std::string *binary_name, boost::program_options::options_description *od_all, boost::program_options::variables_map *var_map, bool check_required_configuration=true)
Read the configuration into a Protobuf message using the command line parameters.
goby
The global namespace for the Goby project.
Definition: acomms_constants.h:33
as.h
goby::middleware::ConfigReader::get_positional_options
static void get_positional_options(const google::protobuf::Descriptor *desc, std::vector< PositionalOption > &positional_options)
detail::value_t::binary
@ binary
binary array (ordered collection of bytes)
goby::middleware::ConfigReader::PositionalOption::required
bool required
Definition: configuration_reader.h:101
goby::middleware::ConfigException
indicates a problem with the runtime command line or .cfg file configuration (or –help was given)
Definition: configuration_reader.h:56
goby::middleware::ConfigReader::PositionalOption
Definition: configuration_reader.h:98
goby::middleware::ConfigReader::set_protobuf_program_option
static void set_protobuf_program_option(const boost::program_options::variables_map &vm, google::protobuf::Message &message, const std::string &full_name, const boost::program_options::variable_value &value, bool overwrite_if_exists)
goby::middleware::ConfigReader::PositionalOption::name
std::string name
Definition: configuration_reader.h:100
goby::middleware::ConfigReader::get_protobuf_program_options
static void get_protobuf_program_options(std::map< goby::GobyFieldOptions::ConfigurationOptions::ConfigAction, boost::program_options::options_description > &od_map, const google::protobuf::Descriptor *desc, std::map< std::string, std::string > &environmental_var_map)
goby::middleware::ConfigReader::check_required_cfg
static void check_required_cfg(const google::protobuf::Message &message, const std::string &binary)
Checks that all required fields are set (either via the command line or the configuration file) in th...
goby::middleware::ConfigReader
Class for reading configuration from command line and/or file(s) into a Google Protocol Buffers messa...
Definition: configuration_reader.h:66
google::protobuf::Message
Definition: message.h:189
goby::GobyFieldOptions_ConfigurationOptions::ALWAYS
static const ConfigAction ALWAYS
Definition: option_extensions.pb.h:337
goby::middleware::ConfigReader::PositionalOption::position_max_count
int position_max_count
Definition: configuration_reader.h:102
goby::Exception
simple exception class for goby applications
Definition: exception.h:34
option_extensions.pb.h
exception.h
goby::middleware::ConfigException::ConfigException
ConfigException(const std::string &s)
Definition: configuration_reader.h:59
google
Definition: dccl.h:57
goby::middleware::ConfigReader::get_example_cfg_file
static void get_example_cfg_file(google::protobuf::Message *message, std::ostream *human_desc_ss, const std::string &indent="", goby::GobyFieldOptions::ConfigurationOptions::ConfigAction action=goby::GobyFieldOptions::ConfigurationOptions::ALWAYS)