Main MRPT website > C++ reference for MRPT 1.9.9
config/CConfigFileBase.h
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 #pragma once
10 
11 #include <string>
12 #include <vector>
13 #include <type_traits>
14 #include <mrpt/system/string_utils.h> // tokenize
15 #include <mrpt/core/exceptions.h>
16 #include <mrpt/core/bits_math.h> // DEG2RAD()
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  template <typename enum_t,
85  void write(
86  const std::string& section, const std::string& name, enum_t value,
87  const int name_padding_width = -1, const int value_padding_width = -1,
88  const std::string& comment = std::string())
89  {
90  this->write(
92  name_padding_width, value_padding_width, comment);
93  }
94  /** @name Save a configuration parameter. Optionally pads with spaces up to
95  * the desired width in number of characters (-1: no fill), and add a final
96  * comment field at the end of the line (a "// " prefix is automatically
97  * inserted).
98  * @{ */
99  template <typename data_t,
101  void write(
102  const std::string& section, const std::string& name,
103  const data_t& value, const int name_padding_width = -1,
104  const int value_padding_width = -1,
105  const std::string& comment = std::string())
106  {
107  writeString(
108  section, name, mrpt::to_string(value), name_padding_width,
109  value_padding_width, comment);
110  }
111  template <typename data_t>
112  void write(
113  const std::string& section, const std::string& name,
114  const std::vector<data_t>& value, const int name_padding_width = -1,
115  const int value_padding_width = -1,
116  const std::string& comment = std::string())
117  {
118  std::string s;
119  for (typename std::vector<data_t>::const_iterator it = value.begin();
120  it != value.end(); ++it)
121  {
122  s += mrpt::to_string(*it);
123  s += " ";
124  }
125  writeString(
126  section, name, s, name_padding_width, value_padding_width, comment);
127  }
128  void write(
129  const std::string& section, const std::string& name, double value,
130  const int name_padding_width = -1, const int value_padding_width = -1,
131  const std::string& comment = std::string());
132  void write(
133  const std::string& section, const std::string& name, float value,
134  const int name_padding_width = -1, const int value_padding_width = -1,
135  const std::string& comment = std::string());
136 
137  /** @} */
138 
139  /** @name Read a configuration parameter, launching exception if key name is
140  * not found and `failIfNotFound`=true
141  * @{ */
142  double read_double(
143  const std::string& section, const std::string& name,
144  double defaultValue, bool failIfNotFound = false) const;
145  float read_float(
146  const std::string& section, const std::string& name, float defaultValue,
147  bool failIfNotFound = false) const;
148  bool read_bool(
149  const std::string& section, const std::string& name, bool defaultValue,
150  bool failIfNotFound = false) const;
151  int read_int(
152  const std::string& section, const std::string& name, int defaultValue,
153  bool failIfNotFound = false) const;
155  const std::string& section, const std::string& name,
156  uint64_t defaultValue, bool failIfNotFound = false) const;
158  const std::string& section, const std::string& name,
159  const std::string& defaultValue, bool failIfNotFound = false) const;
160  /** Reads a configuration parameter of type "string", and keeps only the
161  * first word (this can be used to eliminate possible comments at the end of
162  * the line) */
164  const std::string& section, const std::string& name,
165  const std::string& defaultValue, bool failIfNotFound = false) const;
166  /** Reads a configuration parameter of type vector, stored in the file as a
167  * string: "[v1 v2 v3 ... ]", where spaces could also be commas. \exception
168  * std::exception If the key name is not found and "failIfNotFound" is true.
169  * Otherwise the "defaultValue" is returned. */
170  template <class VECTOR_TYPE>
172  const std::string& section, const std::string& name,
173  const VECTOR_TYPE& defaultValue, VECTOR_TYPE& outValues,
174  bool failIfNotFound = false) const
175  {
176  std::string aux(readString(section, name, "", failIfNotFound));
177  // Parse the text into a vector:
178  std::vector<std::string> tokens;
179  mrpt::system::tokenize(aux, "[], \t", tokens);
180 
181  if (tokens.size() == 0)
182  {
183  outValues = defaultValue;
184  }
185  else
186  {
187  // Parse to numeric type:
188  const size_t N = tokens.size();
189  outValues.resize(N);
190  for (size_t i = 0; i < N; i++)
191  {
192  double val = std::stod(tokens[i]);
193  outValues[i] = val;
194  }
195  }
196  }
197 
198  /** Reads a configuration parameter as a matrix written in a matlab-like
199  * format - for example: "[2 3 4 ; 7 8 9]".
200  * This template method can be instantiated for matrices of the types: int,
201  * long, unsinged int, unsigned long, float, double, long double
202  * \exception std::exception If the key name is not found and
203  * "failIfNotFound" is true. Otherwise the "defaultValue" is returned.
204  */
205  template <class MATRIX_TYPE>
207  const std::string& section, const std::string& name,
208  MATRIX_TYPE& outMatrix,
209  const MATRIX_TYPE& defaultMatrix = MATRIX_TYPE(),
210  bool failIfNotFound = false) const
211  {
212  std::string aux = readString(section, name, "", failIfNotFound);
213  if (aux.empty())
214  outMatrix = defaultMatrix;
215  else
216  {
217  // Parse the text into a vector:
218  if (!outMatrix.fromMatlabStringFormat(aux))
219  THROW_EXCEPTION_FMT("Error parsing matrix: '%s'", aux.c_str())
220  }
221  }
222 
223  /** Reads an "enum" value, where the value in the config file can be either
224  * a numerical value or the symbolic name, for example:
225  * In the code:
226  * \code
227  * enum my_type_t { type_foo=0, type_bar };
228  * \endcode
229  * In the config file:
230  * \code
231  * [section]
232  * type = type_bar // Use the symbolic name, or
233  * type = 1 // use the numerical value (both lines will be
234  * equivalent)
235  * \endcode
236  * Which can be loaded with:
237  * \code
238  * cfgfile.read_enum<my_type_t>("section","type", type_foo );
239  * \endcode
240  *
241  * \note For an enum type to work with this template it is required that
242  * it defines a specialization of mrpt::typemeta::TEnumType
243  */
244  template <typename ENUMTYPE>
245  ENUMTYPE read_enum(
246  const std::string& section, const std::string& name,
247  const ENUMTYPE& defaultValue, bool failIfNotFound = false) const
248  {
249  MRPT_START
250  const std::string sVal =
251  read_string_first_word(section, name, "", failIfNotFound);
252  if (sVal.empty()) return defaultValue;
253  // Text or numeric value?
254  if (::isdigit(sVal[0]))
255  { // Seems a number:
256  return static_cast<ENUMTYPE>(::atoi(&sVal[0]));
257  }
258  else
259  { // Name look-up:
260  try
261  {
263  }
264  catch (std::exception&)
265  {
267  "Invalid value '%s' for enum type while reading key='%s'.",
268  sVal.c_str(), name.c_str())
269  }
270  }
271  MRPT_END
272  }
273  /** @} */
274 }; // End of class def.
275 
276 /** An useful macro for loading variables stored in a INI-like file under a key
277  * with the same name that the variable, and assigning the variable the current
278  * value if not found in the config file.
279  * The variableType must be the suffix of "read_XXX" functions, i.e. int,
280  * bool,...
281  */
282 #define MRPT_LOAD_CONFIG_VAR( \
283  variableName, variableType, configFileObject, sectionNameStr) \
284  { \
285  variableName = configFileObject.read_##variableType( \
286  sectionNameStr, #variableName, variableName); \
287  }
288 
289 /** Shortcut for MRPT_LOAD_CONFIG_VAR() for config file object named `c` and
290  * section string named `s` */
291 #define MRPT_LOAD_CONFIG_VAR_CS(variableName, variableType) \
292  MRPT_LOAD_CONFIG_VAR(variableName, variableType, c, s)
293 
294 /** Loads a double variable, stored as radians but entered in the INI-file as
295  * degrees */
296 #define MRPT_LOAD_CONFIG_VAR_DEGREES( \
297  variableName, configFileObject, sectionNameStr) \
298  { \
299  variableName = mrpt::DEG2RAD( \
300  configFileObject.read_double( \
301  sectionNameStr, #variableName, mrpt::RAD2DEG(variableName))); \
302  }
303 
304 /** Loads a double, required, variable, stored as radians but entered in the
305  * INI-file as degrees */
306 #define MRPT_LOAD_CONFIG_VAR_DEGREES_NO_DEFAULT( \
307  variableName, configFileObject, sectionNameStr) \
308  { \
309  variableName = mrpt::DEG2RAD( \
310  configFileObject.read_double( \
311  sectionNameStr, #variableName, mrpt::RAD2DEG(variableName), \
312  true)); \
313  }
314 
315 #define MRPT_LOAD_CONFIG_VAR_CAST( \
316  variableName, variableType, variableTypeCast, configFileObject, \
317  sectionNameStr) \
318  { \
319  variableName = static_cast<variableTypeCast>( \
320  configFileObject.read_##variableType( \
321  sectionNameStr, #variableName, variableName)); \
322  }
323 
324 #define MRPT_LOAD_HERE_CONFIG_VAR( \
325  variableName, variableType, targetVariable, configFileObject, \
326  sectionNameStr) \
327  targetVariable = configFileObject.read_##variableType( \
328  sectionNameStr, #variableName, targetVariable, false);
329 
330 #define MRPT_LOAD_HERE_CONFIG_VAR_NO_DEFAULT( \
331  variableName, variableType, targetVariable, configFileObject, \
332  sectionNameStr) \
333  { \
334  try \
335  { \
336  targetVariable = configFileObject.read_##variableType( \
337  sectionNameStr, #variableName, targetVariable, true); \
338  } \
339  catch (std::exception&) \
340  { \
341  THROW_EXCEPTION( \
342  mrpt::format( \
343  "Value for '%s' not found in config file in section '%s'", \
344  static_cast<const char*>(#variableName), \
345  std::string(sectionNameStr).c_str())); \
346  } \
347  }
348 
349 #define MRPT_LOAD_HERE_CONFIG_VAR_DEGREES( \
350  variableName, variableType, targetVariable, configFileObject, \
351  sectionNameStr) \
352  targetVariable = mrpt::DEG2RAD( \
353  configFileObject.read_##variableType( \
354  sectionNameStr, #variableName, mrpt::RAD2DEG(targetVariable), \
355  false));
356 
357 #define MRPT_LOAD_HERE_CONFIG_VAR_DEGREES_NO_DEFAULT( \
358  variableName, variableType, targetVariable, configFileObject, \
359  sectionNameStr) \
360  { \
361  try \
362  { \
363  targetVariable = mrpt::DEG2RAD( \
364  configFileObject.read_##variableType( \
365  sectionNameStr, #variableName, targetVariable, true)); \
366  } \
367  catch (std::exception&) \
368  { \
369  THROW_EXCEPTION( \
370  mrpt::format( \
371  "Value for '%s' not found in config file in section '%s'", \
372  static_cast<const char*>(#variableName), \
373  std::string(sectionNameStr).c_str())); \
374  } \
375  }
376 
377 #define MRPT_LOAD_CONFIG_VAR_NO_DEFAULT( \
378  variableName, variableType, configFileObject, sectionNameStr) \
379  { \
380  try \
381  { \
382  variableName = configFileObject.read_##variableType( \
383  sectionNameStr, #variableName, variableName, true); \
384  } \
385  catch (std::exception&) \
386  { \
387  THROW_EXCEPTION( \
388  mrpt::format( \
389  "Value for '%s' not found in config file in section '%s'", \
390  static_cast<const char*>(#variableName), \
391  std::string(sectionNameStr).c_str())); \
392  } \
393  }
394 
395 /** Shortcut for MRPT_LOAD_CONFIG_VAR_NO_DEFAULT() for REQUIRED variables config
396  * file object named `c` and section string named `s` */
397 #define MRPT_LOAD_CONFIG_VAR_REQUIRED_CS(variableName, variableType) \
398  MRPT_LOAD_CONFIG_VAR_NO_DEFAULT(variableName, variableType, c, s)
399 
400 #define MRPT_LOAD_CONFIG_VAR_CAST_NO_DEFAULT( \
401  variableName, variableType, variableTypeCast, configFileObject, \
402  sectionNameStr) \
403  { \
404  try \
405  { \
406  variableName = static_cast<variableTypeCast>( \
407  configFileObject.read_##variableType( \
408  sectionNameStr, #variableName, variableName, true)); \
409  } \
410  catch (std::exception&) \
411  { \
412  THROW_EXCEPTION( \
413  mrpt::format( \
414  "Value for '%s' not found in config file in section '%s'", \
415  static_cast<const char*>(#variableName), \
416  std::string(sectionNameStr).c_str())); \
417  } \
418  }
419 
420 #define MRPT_LOAD_HERE_CONFIG_VAR_CAST( \
421  variableName, variableType, variableTypeCast, targetVariable, \
422  configFileObject, sectionNameStr) \
423  targetVariable = static_cast<variableTypeCast>( \
424  configFileObject.read_##variableType( \
425  sectionNameStr, #variableName, targetVariable));
426 
427 #define MRPT_LOAD_HERE_CONFIG_VAR_CAST_NO_DEFAULT( \
428  variableName, variableType, variableTypeCast, targetVariable, \
429  configFileObject, sectionNameStr) \
430  { \
431  try \
432  { \
433  targetVariable = static_cast<variableTypeCast>( \
434  configFileObject.read_##variableType( \
435  sectionNameStr, #variableName, targetVariable, true)); \
436  } \
437  catch (std::exception&) \
438  { \
439  THROW_EXCEPTION( \
440  mrpt::format( \
441  "Value for '%s' not found in config file in section '%s'", \
442  static_cast<const char*>(#variableName), \
443  std::string(sectionNameStr).c_str())); \
444  } \
445  }
446 
447 #define MRPT_SAVE_CONFIG_VAR(variableName, configFileObject, sectionNameStr) \
448  { \
449  configFileObject.write(sectionNameStr, #variableName, variableName); \
450  }
451 
452 #define MRPT_SAVE_CONFIG_VAR_DEGREES( \
453  variableName, configFileObject, sectionNameStr) \
454  { \
455  configFileObject.write( \
456  sectionNameStr, #variableName, mrpt::RAD2DEG(variableName)); \
457  }
458 
459 #define MRPT_SAVE_CONFIG_VAR_COMMENT(variableName, __comment) \
460  { \
461  c.write( \
462  s, #variableName, variableName, \
463  mrpt::config::MRPT_SAVE_NAME_PADDING(), \
464  mrpt::config::MRPT_SAVE_VALUE_PADDING(), __comment); \
465  }
466 #define MRPT_SAVE_CONFIG_VAR_DEGREES_COMMENT( \
467  __entryName, __variable, __comment) \
468  { \
469  c.write( \
470  s, __entryName, mrpt::RAD2DEG(__variable), \
471  mrpt::config::MRPT_SAVE_NAME_PADDING(), \
472  mrpt::config::MRPT_SAVE_VALUE_PADDING(), __comment); \
473  }
474 
475 } // End of namespace
476 } // end of namespace
#define MRPT_START
Definition: exceptions.h:262
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:96
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:3676
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...
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:955
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:4101
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:50
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
bool read_bool(const std::string &section, const std::string &name, bool defaultValue, bool failIfNotFound=false) const
#define MRPT_END
Definition: exceptions.h:266
GLuint const GLchar * name
Definition: glext.h:4054
GLsizei const GLfloat * value
Definition: glext.h:4117
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:43
const Scalar * const_iterator
Definition: eigen_plugins.h:27
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:27
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: ad3a9d8ae Tue May 1 23:10:22 2018 -0700 at lun oct 28 00:14:14 CET 2019