MRPT  1.9.9
config/CConfigFileBase.h
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2019, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 #pragma once
10 
11 #include <mrpt/core/bits_math.h> // DEG2RAD()
12 #include <mrpt/core/exceptions.h>
13 #include <mrpt/system/string_utils.h> // tokenize
14 #include <string>
15 #include <type_traits>
16 #include <vector>
17 
18 namespace mrpt
19 {
20 // Frd decl:
21 namespace typemeta
22 {
23 template <typename ENUMTYPE>
24 struct TEnumType;
25 }
26 namespace config
27 {
28 // Frwd. decl:
29 class CConfigFilePrefixer;
30 
31 /** Default padding sizes for macros MRPT_SAVE_CONFIG_VAR_COMMENT(), etc. */
34 
35 /** This class allows loading and storing values and vectors of different types
36  * from a configuration text, which can be implemented as a ".ini" file, a
37  * memory-stored string, etc...
38  * This is a virtual class, use only as a pointer to an implementation of one
39  * of the derived classes.
40  *
41  * See: \ref config_file_format
42  * \ingroup mrpt_base_grp
43  */
45 {
46  friend class CConfigFilePrefixer;
47 
48  protected:
49  /** A virtual method to write a generic string.
50  */
51  virtual void writeString(
52  const std::string& section, const std::string& name,
53  const std::string& str) = 0;
54 
55  /** Write a generic string with optional padding and a comment field ("//
56  * ...") at the end of the line. */
57  void writeString(
58  const std::string& section, const std::string& name,
59  const std::string& str, const int name_padding_width,
60  const int value_padding_width, const std::string& comment);
61 
62  /** A virtual method to read a generic string.
63  * \exception std::exception If the key name is not found and
64  * "failIfNotFound" is true. Otherwise the "defaultValue" is returned. */
65  virtual std::string readString(
66  const std::string& section, const std::string& name,
67  const std::string& defaultStr, bool failIfNotFound = false) const = 0;
68 
69  public:
70  /** dtor */
71  virtual ~CConfigFileBase();
72 
73  /** Returns a list with all the section names. */
74  virtual void getAllSections(std::vector<std::string>& sections) const = 0;
75 
76  /** Returs a list with all the keys into a section */
77  virtual void getAllKeys(
78  const std::string& section, std::vector<std::string>& keys) const = 0;
79 
80  /** Checks if a given section exists (name is case insensitive) */
81  bool sectionExists(const std::string& section_name) const;
82 
83  /** Changes the contents of the virtual "config file" from a text block
84  * containing a YAML configuration text. Refer to unit test
85  * yaml2config_unittest.cpp for examples of use.
86  * \sa getContentAsYAML()
87  */
88  void setContentFromYAML(const std::string& yaml_block);
89 
90  /** Returns a text block representing the contents of the config file in
91  * YAML format.
92  * \sa setContentFromYAML()
93  */
95 
96  /** Empties the "config file" */
97  virtual void clear() = 0;
98 
99  template <
100  typename enum_t,
102  void write(
103  const std::string& section, const std::string& name, enum_t value,
104  const int name_padding_width = -1, const int value_padding_width = -1,
105  const std::string& comment = std::string())
106  {
107  this->write(
109  name_padding_width, value_padding_width, comment);
110  }
111  /** @name Save a configuration parameter. Optionally pads with spaces up to
112  * the desired width in number of characters (-1: no fill), and add a final
113  * comment field at the end of the line (a "// " prefix is automatically
114  * inserted).
115  * @{ */
116  template <
117  typename data_t,
119  void write(
120  const std::string& section, const std::string& name,
121  const data_t& value, const int name_padding_width = -1,
122  const int value_padding_width = -1,
123  const std::string& comment = std::string())
124  {
125  writeString(
126  section, name, mrpt::to_string(value), name_padding_width,
127  value_padding_width, comment);
128  }
129  template <typename data_t>
130  void write(
131  const std::string& section, const std::string& name,
132  const std::vector<data_t>& value, const int name_padding_width = -1,
133  const int value_padding_width = -1,
134  const std::string& comment = std::string())
135  {
136  std::string s;
137  for (typename std::vector<data_t>::const_iterator it = value.begin();
138  it != value.end(); ++it)
139  {
140  s += mrpt::to_string(*it);
141  s += " ";
142  }
143  writeString(
144  section, name, s, name_padding_width, value_padding_width, comment);
145  }
146  void write(
147  const std::string& section, const std::string& name, double value,
148  const int name_padding_width = -1, const int value_padding_width = -1,
149  const std::string& comment = std::string());
150  void write(
151  const std::string& section, const std::string& name, float value,
152  const int name_padding_width = -1, const int value_padding_width = -1,
153  const std::string& comment = std::string());
154 
155  /** @} */
156 
157  /** @name Read a configuration parameter, launching exception if key name is
158  * not found and `failIfNotFound`=true
159  * @{ */
160  double read_double(
161  const std::string& section, const std::string& name,
162  double defaultValue, bool failIfNotFound = false) const;
163  float read_float(
164  const std::string& section, const std::string& name, float defaultValue,
165  bool failIfNotFound = false) const;
166  bool read_bool(
167  const std::string& section, const std::string& name, bool defaultValue,
168  bool failIfNotFound = false) const;
169  int read_int(
170  const std::string& section, const std::string& name, int defaultValue,
171  bool failIfNotFound = false) const;
173  const std::string& section, const std::string& name,
174  uint64_t defaultValue, bool failIfNotFound = false) const;
176  const std::string& section, const std::string& name,
177  const std::string& defaultValue, bool failIfNotFound = false) const;
178  /** Reads a configuration parameter of type "string", and keeps only the
179  * first word (this can be used to eliminate possible comments at the end of
180  * the line) */
182  const std::string& section, const std::string& name,
183  const std::string& defaultValue, bool failIfNotFound = false) const;
184  /** Reads a configuration parameter of type vector, stored in the file as a
185  * string: "[v1 v2 v3 ... ]", where spaces could also be commas. \exception
186  * std::exception If the key name is not found and "failIfNotFound" is true.
187  * Otherwise the "defaultValue" is returned. */
188  template <class VECTOR_TYPE>
190  const std::string& section, const std::string& name,
191  const VECTOR_TYPE& defaultValue, VECTOR_TYPE& outValues,
192  bool failIfNotFound = false) const
193  {
194  std::string aux(readString(section, name, "", failIfNotFound));
195  // Parse the text into a vector:
196  std::vector<std::string> tokens;
197  mrpt::system::tokenize(aux, "[], \t", tokens);
198 
199  if (tokens.size() == 0)
200  {
201  outValues = defaultValue;
202  }
203  else
204  {
205  // Parse to numeric type:
206  const size_t N = tokens.size();
207  outValues.resize(N);
208  for (size_t i = 0; i < N; i++)
209  {
210  double val = std::stod(tokens[i]);
211  outValues[i] = val;
212  }
213  }
214  }
215 
216  /** Reads a configuration parameter as a matrix written in a matlab-like
217  * format - for example: "[2 3 4 ; 7 8 9]".
218  * This template method can be instantiated for matrices of the types: int,
219  * long, unsinged int, unsigned long, float, double, long double
220  * \exception std::exception If the key name is not found and
221  * "failIfNotFound" is true. Otherwise the "defaultValue" is returned.
222  */
223  template <class MATRIX_TYPE>
225  const std::string& section, const std::string& name,
226  MATRIX_TYPE& outMatrix,
227  const MATRIX_TYPE& defaultMatrix = MATRIX_TYPE(),
228  bool failIfNotFound = false) const
229  {
230  std::string aux = readString(section, name, "", failIfNotFound);
231  if (aux.empty())
232  outMatrix = defaultMatrix;
233  else
234  {
235  // Parse the text into a vector:
236  if (!outMatrix.fromMatlabStringFormat(aux))
237  THROW_EXCEPTION_FMT("Error parsing matrix: '%s'", aux.c_str());
238  }
239  }
240 
241  /** Reads an "enum" value, where the value in the config file can be either
242  * a numerical value or the symbolic name, for example:
243  * In the code:
244  * \code
245  * enum my_type_t { type_foo=0, type_bar };
246  * \endcode
247  * In the config file:
248  * \code
249  * [section]
250  * type = type_bar // Use the symbolic name, or
251  * type = 1 // use the numerical value (both lines will be
252  * equivalent)
253  * \endcode
254  * Which can be loaded with:
255  * \code
256  * cfgfile.read_enum<my_type_t>("section","type", type_foo );
257  * \endcode
258  *
259  * \note For an enum type to work with this template it is required that
260  * it defines a specialization of mrpt::typemeta::TEnumType
261  */
262  template <typename ENUMTYPE>
263  ENUMTYPE read_enum(
264  const std::string& section, const std::string& name,
265  const ENUMTYPE& defaultValue, bool failIfNotFound = false) const
266  {
267  MRPT_START
268  const std::string sVal =
269  read_string_first_word(section, name, "", failIfNotFound);
270  if (sVal.empty()) return defaultValue;
271  // Text or numeric value?
272  if (::isdigit(sVal[0]))
273  { // Seems a number:
274  return static_cast<ENUMTYPE>(::atoi(&sVal[0]));
275  }
276  else
277  { // Name look-up:
278  try
279  {
281  }
282  catch (std::exception&)
283  {
285  "Invalid value '%s' for enum type while reading key='%s'.",
286  sVal.c_str(), name.c_str());
287  }
288  }
289  MRPT_END
290  }
291  /** @} */
292 }; // End of class def.
293 
294 /** An useful macro for loading variables stored in a INI-like file under a key
295  * with the same name that the variable, and assigning the variable the current
296  * value if not found in the config file.
297  * The variableType must be the suffix of "read_XXX" functions, i.e. int,
298  * bool,...
299  */
300 #define MRPT_LOAD_CONFIG_VAR( \
301  variableName, variableType, configFileObject, sectionNameStr) \
302  { \
303  variableName = configFileObject.read_##variableType( \
304  sectionNameStr, #variableName, variableName); \
305  }
306 
307 /** Shortcut for MRPT_LOAD_CONFIG_VAR() for config file object named `c` and
308  * section string named `s` */
309 #define MRPT_LOAD_CONFIG_VAR_CS(variableName, variableType) \
310  MRPT_LOAD_CONFIG_VAR(variableName, variableType, c, s)
311 
312 /** Loads a double variable, stored as radians but entered in the INI-file as
313  * degrees */
314 #define MRPT_LOAD_CONFIG_VAR_DEGREES( \
315  variableName, configFileObject, sectionNameStr) \
316  { \
317  variableName = mrpt::DEG2RAD(configFileObject.read_double( \
318  sectionNameStr, #variableName, mrpt::RAD2DEG(variableName))); \
319  }
320 
321 /** Loads a double, required, variable, stored as radians but entered in the
322  * INI-file as degrees */
323 #define MRPT_LOAD_CONFIG_VAR_DEGREES_NO_DEFAULT( \
324  variableName, configFileObject, sectionNameStr) \
325  { \
326  variableName = mrpt::DEG2RAD(configFileObject.read_double( \
327  sectionNameStr, #variableName, mrpt::RAD2DEG(variableName), \
328  true)); \
329  }
330 
331 #define MRPT_LOAD_CONFIG_VAR_CAST( \
332  variableName, variableType, variableTypeCast, configFileObject, \
333  sectionNameStr) \
334  { \
335  variableName = static_cast<variableTypeCast>( \
336  configFileObject.read_##variableType( \
337  sectionNameStr, #variableName, variableName)); \
338  }
339 
340 #define MRPT_LOAD_HERE_CONFIG_VAR( \
341  variableName, variableType, targetVariable, configFileObject, \
342  sectionNameStr) \
343  targetVariable = configFileObject.read_##variableType( \
344  sectionNameStr, #variableName, targetVariable, false);
345 
346 #define MRPT_LOAD_HERE_CONFIG_VAR_NO_DEFAULT( \
347  variableName, variableType, targetVariable, configFileObject, \
348  sectionNameStr) \
349  { \
350  try \
351  { \
352  targetVariable = configFileObject.read_##variableType( \
353  sectionNameStr, #variableName, targetVariable, true); \
354  } \
355  catch (std::exception&) \
356  { \
357  THROW_EXCEPTION(mrpt::format( \
358  "Value for '%s' not found in config file in section '%s'", \
359  static_cast<const char*>(#variableName), \
360  std::string(sectionNameStr).c_str())); \
361  } \
362  }
363 
364 #define MRPT_LOAD_HERE_CONFIG_VAR_DEGREES( \
365  variableName, variableType, targetVariable, configFileObject, \
366  sectionNameStr) \
367  targetVariable = mrpt::DEG2RAD(configFileObject.read_##variableType( \
368  sectionNameStr, #variableName, mrpt::RAD2DEG(targetVariable), false));
369 
370 #define MRPT_LOAD_HERE_CONFIG_VAR_DEGREES_NO_DEFAULT( \
371  variableName, variableType, targetVariable, configFileObject, \
372  sectionNameStr) \
373  { \
374  try \
375  { \
376  targetVariable = \
377  mrpt::DEG2RAD(configFileObject.read_##variableType( \
378  sectionNameStr, #variableName, targetVariable, true)); \
379  } \
380  catch (std::exception&) \
381  { \
382  THROW_EXCEPTION(mrpt::format( \
383  "Value for '%s' not found in config file in section '%s'", \
384  static_cast<const char*>(#variableName), \
385  std::string(sectionNameStr).c_str())); \
386  } \
387  }
388 
389 #define MRPT_LOAD_CONFIG_VAR_NO_DEFAULT( \
390  variableName, variableType, configFileObject, sectionNameStr) \
391  { \
392  try \
393  { \
394  variableName = configFileObject.read_##variableType( \
395  sectionNameStr, #variableName, variableName, true); \
396  } \
397  catch (std::exception&) \
398  { \
399  THROW_EXCEPTION(mrpt::format( \
400  "Value for '%s' not found in config file in section '%s'", \
401  static_cast<const char*>(#variableName), \
402  std::string(sectionNameStr).c_str())); \
403  } \
404  }
405 
406 /** Shortcut for MRPT_LOAD_CONFIG_VAR_NO_DEFAULT() for REQUIRED variables config
407  * file object named `c` and section string named `s` */
408 #define MRPT_LOAD_CONFIG_VAR_REQUIRED_CS(variableName, variableType) \
409  MRPT_LOAD_CONFIG_VAR_NO_DEFAULT(variableName, variableType, c, s)
410 
411 #define MRPT_LOAD_CONFIG_VAR_CAST_NO_DEFAULT( \
412  variableName, variableType, variableTypeCast, configFileObject, \
413  sectionNameStr) \
414  { \
415  try \
416  { \
417  variableName = static_cast<variableTypeCast>( \
418  configFileObject.read_##variableType( \
419  sectionNameStr, #variableName, variableName, true)); \
420  } \
421  catch (std::exception&) \
422  { \
423  THROW_EXCEPTION(mrpt::format( \
424  "Value for '%s' not found in config file in section '%s'", \
425  static_cast<const char*>(#variableName), \
426  std::string(sectionNameStr).c_str())); \
427  } \
428  }
429 
430 #define MRPT_LOAD_HERE_CONFIG_VAR_CAST( \
431  variableName, variableType, variableTypeCast, targetVariable, \
432  configFileObject, sectionNameStr) \
433  targetVariable = \
434  static_cast<variableTypeCast>(configFileObject.read_##variableType( \
435  sectionNameStr, #variableName, targetVariable));
436 
437 #define MRPT_LOAD_HERE_CONFIG_VAR_CAST_NO_DEFAULT( \
438  variableName, variableType, variableTypeCast, targetVariable, \
439  configFileObject, sectionNameStr) \
440  { \
441  try \
442  { \
443  targetVariable = static_cast<variableTypeCast>( \
444  configFileObject.read_##variableType( \
445  sectionNameStr, #variableName, targetVariable, true)); \
446  } \
447  catch (std::exception&) \
448  { \
449  THROW_EXCEPTION(mrpt::format( \
450  "Value for '%s' not found in config file in section '%s'", \
451  static_cast<const char*>(#variableName), \
452  std::string(sectionNameStr).c_str())); \
453  } \
454  }
455 
456 #define MRPT_SAVE_CONFIG_VAR(variableName, configFileObject, sectionNameStr) \
457  { \
458  configFileObject.write(sectionNameStr, #variableName, variableName); \
459  }
460 
461 #define MRPT_SAVE_CONFIG_VAR_DEGREES( \
462  variableName, configFileObject, sectionNameStr) \
463  { \
464  configFileObject.write( \
465  sectionNameStr, #variableName, mrpt::RAD2DEG(variableName)); \
466  }
467 
468 #define MRPT_SAVE_CONFIG_VAR_COMMENT(variableName, __comment) \
469  { \
470  c.write( \
471  s, #variableName, variableName, \
472  mrpt::config::MRPT_SAVE_NAME_PADDING(), \
473  mrpt::config::MRPT_SAVE_VALUE_PADDING(), __comment); \
474  }
475 #define MRPT_SAVE_CONFIG_VAR_DEGREES_COMMENT( \
476  __entryName, __variable, __comment) \
477  { \
478  c.write( \
479  s, __entryName, mrpt::RAD2DEG(__variable), \
480  mrpt::config::MRPT_SAVE_NAME_PADDING(), \
481  mrpt::config::MRPT_SAVE_VALUE_PADDING(), __comment); \
482  }
483 
484 } // namespace config
485 } // namespace mrpt
#define MRPT_START
Definition: exceptions.h:241
virtual void getAllKeys(const std::string &section, std::vector< std::string > &keys) const =0
Returs a list with all the keys into a section.
std::string read_string(const std::string &section, const std::string &name, const std::string &defaultValue, bool failIfNotFound=false) const
static ENUMTYPE name2value(const std::string &name)
Gives the numerical name for a given enum text name.
Definition: TEnumType.h:100
int MRPT_SAVE_NAME_PADDING()
Default padding sizes for macros MRPT_SAVE_CONFIG_VAR_COMMENT(), etc.
void read_matrix(const std::string &section, const std::string &name, MATRIX_TYPE &outMatrix, const MATRIX_TYPE &defaultMatrix=MATRIX_TYPE(), bool failIfNotFound=false) const
Reads a configuration parameter as a matrix written in a matlab-like format - for example: "[2 3 4 ; ...
void write(const std::string &section, const std::string &name, const data_t &value, const int name_padding_width=-1, const int value_padding_width=-1, const std::string &comment=std::string())
float read_float(const std::string &section, const std::string &name, float defaultValue, bool failIfNotFound=false) const
virtual void writeString(const std::string &section, const std::string &name, const std::string &str)=0
A virtual method to write a generic string.
GLdouble s
Definition: glext.h:3682
void tokenize(const std::string &inString, const std::string &inDelimiters, OUT_CONTAINER &outTokens, bool skipBlankTokens=true) noexcept
Tokenizes a string according to a set of delimiting characters.
int read_int(const std::string &section, const std::string &name, int defaultValue, bool failIfNotFound=false) const
ENUMTYPE read_enum(const std::string &section, const std::string &name, const ENUMTYPE &defaultValue, bool failIfNotFound=false) const
Reads an "enum" value, where the value in the config file can be either a numerical value or the symb...
This class allows loading and storing values and vectors of different types from a configuration text...
void setContentFromYAML(const std::string &yaml_block)
Changes the contents of the virtual "config file" from a text block containing a YAML configuration t...
A helper class that can convert an enum value into its textual representation, and viceversa...
virtual void getAllSections(std::vector< std::string > &sections) const =0
Returns a list with all the section names.
int val
Definition: mrpt_jpeglib.h:957
uint64_t read_uint64_t(const std::string &section, const std::string &name, uint64_t defaultValue, bool failIfNotFound=false) const
int MRPT_SAVE_VALUE_PADDING()
std::string read_string_first_word(const std::string &section, const std::string &name, const std::string &defaultValue, bool failIfNotFound=false) const
Reads a configuration parameter of type "string", and keeps only the first word (this can be used to ...
bool sectionExists(const std::string &section_name) const
Checks if a given section exists (name is case insensitive)
A wrapper for other CConfigFileBase-based objects that prefixes a given token to every key and/or sec...
double read_double(const std::string &section, const std::string &name, double defaultValue, bool failIfNotFound=false) const
GLsizei const GLchar ** string
Definition: glext.h:4116
void write(const std::string &section, const std::string &name, enum_t value, const int name_padding_width=-1, const int value_padding_width=-1, const std::string &comment=std::string())
unsigned __int64 uint64_t
Definition: rptypes.h:53
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
virtual void clear()=0
Empties the "config file".
bool read_bool(const std::string &section, const std::string &name, bool defaultValue, bool failIfNotFound=false) const
#define MRPT_END
Definition: exceptions.h:245
GLuint const GLchar * name
Definition: glext.h:4068
std::string std::string to_string(T v)
Just like std::to_string(), but with an overloaded version for std::string arguments.
Definition: format.h:30
GLsizei const GLfloat * value
Definition: glext.h:4134
std::string getContentAsYAML() const
Returns a text block representing the contents of the config file in YAML format. ...
void write(const std::string &section, const std::string &name, const std::vector< data_t > &value, const int name_padding_width=-1, const int value_padding_width=-1, const std::string &comment=std::string())
#define THROW_EXCEPTION_FMT(_FORMAT_STRING,...)
Definition: exceptions.h:69
void read_vector(const std::string &section, const std::string &name, const VECTOR_TYPE &defaultValue, VECTOR_TYPE &outValues, bool failIfNotFound=false) const
Reads a configuration parameter of type vector, stored in the file as a string: "[v1 v2 v3 ...
virtual std::string readString(const std::string &section, const std::string &name, const std::string &defaultStr, bool failIfNotFound=false) const =0
A virtual method to read a generic string.



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 8fe78517f Sun Jul 14 19:43:28 2019 +0200 at lun oct 28 02:10:00 CET 2019