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