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



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019