Main MRPT website > C++ reference
MRPT logo

CConfigFileBase.h

Go to the documentation of this file.
00001 /* +---------------------------------------------------------------------------+
00002    |          The Mobile Robot Programming Toolkit (MRPT) C++ library          |
00003    |                                                                           |
00004    |                   http://mrpt.sourceforge.net/                            |
00005    |                                                                           |
00006    |   Copyright (C) 2005-2011  University of Malaga                           |
00007    |                                                                           |
00008    |    This software was written by the Machine Perception and Intelligent    |
00009    |      Robotics Lab, University of Malaga (Spain).                          |
00010    |    Contact: Jose-Luis Blanco  <jlblanco@ctima.uma.es>                     |
00011    |                                                                           |
00012    |  This file is part of the MRPT project.                                   |
00013    |                                                                           |
00014    |     MRPT is free software: you can redistribute it and/or modify          |
00015    |     it under the terms of the GNU General Public License as published by  |
00016    |     the Free Software Foundation, either version 3 of the License, or     |
00017    |     (at your option) any later version.                                   |
00018    |                                                                           |
00019    |   MRPT is distributed in the hope that it will be useful,                 |
00020    |     but WITHOUT ANY WARRANTY; without even the implied warranty of        |
00021    |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         |
00022    |     GNU General Public License for more details.                          |
00023    |                                                                           |
00024    |     You should have received a copy of the GNU General Public License     |
00025    |     along with MRPT.  If not, see <http://www.gnu.org/licenses/>.         |
00026    |                                                                           |
00027    +---------------------------------------------------------------------------+ */
00028 #ifndef  CConfigFileBase_H
00029 #define  CConfigFileBase_H
00030 
00031 #include <mrpt/utils/utils_defs.h>
00032 #include <mrpt/utils/TEnumType.h>
00033 #include <mrpt/math/CMatrixTemplate.h>
00034 #include <mrpt/system/string_utils.h>
00035 
00036 /*---------------------------------------------------------------
00037         Class
00038   ---------------------------------------------------------------*/
00039 namespace mrpt
00040 {
00041 namespace utils
00042 {
00043         /** This class allows loading and storing values and vectors of different types from a configuration text, which can be implemented as a ".ini" file, a memory-stored string, etc...
00044           *   This is a virtual class, use only as a pointer to an implementation of one of the derived classes.
00045           */
00046         class BASE_IMPEXP CConfigFileBase
00047         {
00048         protected:
00049                 /** A virtual method to write a generic string.
00050                   */
00051                 virtual void  writeString(const std::string &section,const std::string &name, const std::string &str) = 0;
00052 
00053                 /** A virtual method to read a generic string.
00054          * \exception std::exception If the key name is not found and "failIfNotFound" is true. Otherwise the "defaultValue" is returned.
00055                  */
00056                 virtual std::string  readString(
00057             const std::string &section,
00058             const std::string &name,
00059             const std::string &defaultStr,
00060             bool failIfNotFound = false) const = 0;
00061 
00062         public:
00063         /** Virtual destructor...
00064          */
00065          virtual ~CConfigFileBase()
00066          {
00067          }
00068 
00069                 /** Returns a list with all the section names.
00070                   */
00071                 virtual void getAllSections( vector_string      &sections ) const = 0 ;
00072 
00073                 /** Returs a list with all the keys into a section.
00074                   */
00075                 virtual void getAllKeys( const std::string section, vector_string       &keys ) const = 0;
00076 
00077                 /** Checks if a given section exists (name is case insensitive) */
00078                 bool sectionExists( const std::string &section_name) const;
00079 
00080                 /** Save a configuration parameter of type "double"
00081                  */
00082                 void  write(const std::string &section, const std::string &name, double value);
00083 
00084                 /** Save a configuration parameter of type "float"
00085                  */
00086                 void  write(const std::string &section, const std::string &name, float value);
00087 
00088                 /** Save a configuration parameter of type "int"
00089                  */
00090                 void  write(const std::string &section, const std::string &name, int value);
00091 
00092                 /** Save a configuration parameter of type "unsigned int"
00093                  */
00094                 void  write(const std::string &section, const std::string &name, unsigned int value);
00095 
00096 #if MRPT_WORD_SIZE>32
00097                 /** Save a configuration parameter of type "size_t"
00098                  */
00099                 void  write(const std::string &section, const std::string &name, size_t value);
00100 #endif
00101 
00102                 /** Save a configuration parameter of type "string"
00103                  */
00104                 void  write(const std::string &section, const std::string &name, const std::string &value);
00105 
00106                 /** Save a configuration parameter of type "std::vector<int>"
00107                  */
00108                 void  write(const std::string &section, const std::string &name, const std::vector<int> &value);
00109 
00110                 /** Save a configuration parameter of type "std::vector<unsigned int>"
00111                  */
00112                 void  write(const std::string &section, const std::string &name, const std::vector<unsigned int> &value);
00113 
00114                 /** Save a configuration parameter of type "std::vector<float>"
00115                  */
00116                 void  write(const std::string &section, const std::string &name, const std::vector<float> &value);
00117 
00118                 /** Save a configuration parameter of type "std::vector<double>"
00119                  */
00120                 void  write(const std::string &section, const std::string &name, const std::vector<double> &value);
00121 
00122                 /** Save a configuration parameter of type "std::vector<bool>"
00123                  */
00124                 void  write(const std::string &section, const std::string &name, const std::vector<bool> &value);
00125 
00126                 /** Reads a configuration parameter of type "double"
00127          * \exception std::exception If the key name is not found and "failIfNotFound" is true. Otherwise the "defaultValue" is returned.
00128                  */
00129                 double  read_double(const std::string &section, const std::string &name, double defaultValue, bool failIfNotFound = false) const;
00130 
00131                 /** Reads a configuration parameter of type "float"
00132          * \exception std::exception If the key name is not found and "failIfNotFound" is true. Otherwise the "defaultValue" is returned.
00133                  */
00134                 float  read_float(const std::string &section, const std::string &name, float defaultValue, bool failIfNotFound = false) const;
00135 
00136                 /** Reads a configuration parameter of type "bool", codified as "1"/"0" or "true"/"false" or "yes"/"no" for true/false, repectively.
00137          * \exception std::exception If the key name is not found and "failIfNotFound" is true. Otherwise the "defaultValue" is returned.
00138                  */
00139                 bool  read_bool(const std::string &section, const std::string &name, bool defaultValue, bool failIfNotFound = false) const;
00140 
00141                 /** Reads a configuration parameter of type "int"
00142          * \exception std::exception If the key name is not found and "failIfNotFound" is true. Otherwise the "defaultValue" is returned.
00143                  */
00144                 int  read_int(const std::string &section, const std::string &name, int defaultValue, bool failIfNotFound = false) const;
00145 
00146                 /** Reads a configuration parameter of type "uint64_t": As in all other methods, the numeric value can be in decimal or hexadecimal with the prefix "0x"
00147          * \exception std::exception If the key name is not found and "failIfNotFound" is true. Otherwise the "defaultValue" is returned.
00148                  */
00149                 uint64_t read_uint64_t(const std::string &section, const std::string &name, uint64_t defaultValue, bool failIfNotFound = false ) const;
00150 
00151                 /** Reads a configuration parameter of type "string"
00152          * \exception std::exception If the key name is not found and "failIfNotFound" is true. Otherwise the "defaultValue" is returned.
00153                  */
00154                 std::string  read_string(const std::string &section, const std::string &name, const std::string &defaultValue, bool failIfNotFound = false) const;
00155 
00156                 /** Reads a configuration parameter of type "string", and keeps only the first word (this can be used to eliminate possible comments at the end of the line)
00157          * \exception std::exception If the key name is not found and "failIfNotFound" is true. Otherwise the "defaultValue" is returned.
00158                  */
00159                 std::string  read_string_first_word(const std::string &section, const std::string &name, const std::string &defaultValue, bool failIfNotFound = false) const;
00160 
00161                 /** Reads a configuration parameter of type vector, stored in the file as a string: "[v1 v2 v3 ... ]", where spaces could also be commas.
00162          * \exception std::exception If the key name is not found and "failIfNotFound" is true. Otherwise the "defaultValue" is returned.
00163                  */
00164                 template <class VECTOR_TYPE>
00165                 void  read_vector(
00166                         const std::string  & section,
00167                         const std::string  & name,
00168                         const VECTOR_TYPE  & defaultValue,
00169                         VECTOR_TYPE        & outValues,
00170                         bool                 failIfNotFound = false) const
00171                 {
00172                         std::string aux ( readString(section, name, "",failIfNotFound ) );
00173                         // Parse the text into a vector:
00174                         std::vector<std::string>        tokens;
00175                         mrpt::system::tokenize( aux,"[], \t",tokens);
00176 
00177                         if (tokens.size()==0)
00178                         {
00179                                 outValues = defaultValue;
00180                         }
00181                         else
00182                         {
00183                                 // Parse to numeric type:
00184                                 const size_t N = tokens.size();
00185                                 outValues.resize( N );
00186                                 for (size_t i=0;i<N;i++)
00187                                 {
00188                                         std::stringstream ss(tokens[i]);
00189                                         ss >> outValues[i];
00190                                 }
00191                         }
00192                 }
00193 
00194 
00195                 /** Reads a configuration parameter as a matrix written in a matlab-like format - for example: "[2 3 4 ; 7 8 9]"
00196                  *  This template method can be instantiated for matrices of the types: int, long, unsinged int, unsigned long, float, double, long double
00197          * \exception std::exception If the key name is not found and "failIfNotFound" is true. Otherwise the "defaultValue" is returned.
00198                  */
00199                  template <class MATRIX_TYPE>
00200                  void read_matrix(
00201                         const std::string                       &section,
00202                         const std::string                       &name,
00203                         MATRIX_TYPE     &outMatrix,
00204                         const MATRIX_TYPE &defaultMatrix = MATRIX_TYPE(),
00205                         bool failIfNotFound = false ) const
00206                 {
00207                         std::string aux = readString(section, name, "",failIfNotFound );
00208                         if (aux.empty())
00209                                 outMatrix = defaultMatrix;
00210                         else
00211                         {
00212                                 // Parse the text into a vector:
00213                                 if (!outMatrix.fromMatlabStringFormat(aux))
00214                                         THROW_EXCEPTION_CUSTOM_MSG1("Error parsing matrix: '%s'",aux.c_str())
00215                         }
00216                 }
00217 
00218                 /** Reads an "enum" value, where the value in the config file can be either a numerical value or the symbolic name, for example:
00219                   *   In the code:
00220                   *  \code
00221                   *    enum my_type_t { type_foo=0, type_bar };
00222                   *  \endcode
00223                   *  In the config file:
00224                   *  \code
00225                   *    [section]
00226                   *    type   = type_bar   // Use the symbolic name, or
00227                   *    type   = 1          // use the numerical value (both lines will be equivalent)
00228                   *  \endcode
00229                   *  Which can be loaded with:
00230                   *  \code
00231                   *    cfgfile.read_enum<my_type_t>("section","type", type_foo );
00232                   *  \endcode
00233                   *
00234                   *  \note For an enum type to work with this template it is required that it defines a specialization of mrpt::utils::TEnumType
00235                   */
00236                 template <typename ENUMTYPE>
00237                 ENUMTYPE read_enum(const std::string &section, const std::string &name, const ENUMTYPE &defaultValue, bool failIfNotFound = false) const
00238                 {
00239                         MRPT_START
00240                         const std::string sVal = read_string_first_word(section,name,"",failIfNotFound);
00241                         if (sVal.empty()) return defaultValue;
00242                         // Text or numeric value?
00243                         if (::isdigit(sVal[0]))
00244                         {       // Seems a number:
00245                                 return static_cast<ENUMTYPE>(::atoi(&sVal[0]));
00246                         }
00247                         else
00248                         {       // Name look-up:
00249                                 try {
00250                                 return mrpt::utils::TEnumType<ENUMTYPE>::name2value(sVal);
00251                                 } catch (std::exception &)
00252                                 {
00253                                         THROW_EXCEPTION(format("Invalid value '%s' for enum type while reading key='%s'.",sVal.c_str(),name.c_str()))
00254                                 }
00255                         }
00256                         MRPT_END
00257                 }
00258 
00259 
00260         }; // End of class def.
00261 
00262         /** An useful macro for loading variables stored in a INI-like file under a key with the same name that the variable, and assigning the variable the current value if not found in the config file.
00263           *  The variableType must be the suffix of "read_XXX" functions, i.e. int, bool,...
00264           */
00265 #define MRPT_LOAD_CONFIG_VAR(variableName,variableType,configFileObject,sectionNameStr) \
00266         { variableName = configFileObject.read_##variableType(sectionNameStr,#variableName,variableName); }
00267 
00268         /** Loads a float variable, stored as radians but entered in the INI-file as degrees:
00269           */
00270 #define MRPT_LOAD_CONFIG_VAR_DEGREES(variableName,configFileObject,sectionNameStr) \
00271         { variableName = DEG2RAD( configFileObject.read_float(sectionNameStr,#variableName, RAD2DEG(variableName)) ); }
00272 
00273 #define MRPT_LOAD_CONFIG_VAR_CAST(variableName,variableType,variableTypeCast,configFileObject,sectionNameStr) \
00274         { variableName = static_cast<variableTypeCast>(configFileObject.read_##variableType(sectionNameStr,#variableName,variableName)); }
00275 
00276 
00277 #define MRPT_LOAD_HERE_CONFIG_VAR(variableName,variableType,targetVariable,configFileObject,sectionNameStr) \
00278                 targetVariable = configFileObject.read_##variableType(sectionNameStr,#variableName,targetVariable,false);
00279 
00280 #define MRPT_LOAD_HERE_CONFIG_VAR_NO_DEFAULT(variableName,variableType,targetVariable,configFileObject,sectionNameStr) \
00281         { try { \
00282                 targetVariable = configFileObject.read_##variableType(sectionNameStr,#variableName,targetVariable,true); \
00283     } catch (std::exception &) \
00284     { \
00285                 THROW_EXCEPTION( format( "Value for '%s' not found in config file", static_cast<const char*>(#variableName ) )); \
00286         } }\
00287 
00288 
00289 #define MRPT_LOAD_CONFIG_VAR_NO_DEFAULT(variableName,variableType,configFileObject,sectionNameStr) \
00290         { try { \
00291                 variableName = configFileObject.read_##variableType(sectionNameStr,#variableName,variableName,true); \
00292     } catch (std::exception &) \
00293     { \
00294                 THROW_EXCEPTION( format( "Value for '%s' not found in config file", static_cast<const char*>(#variableName ) )); \
00295         } }\
00296 
00297 #define MRPT_LOAD_CONFIG_VAR_CAST_NO_DEFAULT(variableName,variableType,variableTypeCast,configFileObject,sectionNameStr) \
00298         { try { \
00299                 variableName = static_cast<variableTypeCast>(configFileObject.read_##variableType(sectionNameStr,#variableName,variableName,true)); \
00300     } catch (std::exception &) \
00301     { \
00302                 THROW_EXCEPTION( format( "Value for '%s' not found in config file", static_cast<const char*>(#variableName ) )); \
00303         } }\
00304 
00305 
00306 #define MRPT_LOAD_HERE_CONFIG_VAR_CAST(variableName,variableType,variableTypeCast,targetVariable,configFileObject,sectionNameStr) \
00307                 targetVariable = static_cast<variableTypeCast>(configFileObject.read_##variableType(sectionNameStr,#variableName,targetVariable));
00308 
00309 #define MRPT_LOAD_HERE_CONFIG_VAR_CAST_NO_DEFAULT(variableName,variableType,variableTypeCast,targetVariable,configFileObject,sectionNameStr) \
00310         { try { \
00311                 targetVariable = static_cast<variableTypeCast>(configFileObject.read_##variableType(sectionNameStr,#variableName,targetVariable,true)); \
00312     } catch (std::exception &) \
00313     { \
00314                 THROW_EXCEPTION( format( "Value for '%s' not found in config file", static_cast<const char*>(#variableName ) )); \
00315         } }\
00316 
00317 
00318 #define MRPT_SAVE_CONFIG_VAR(variableName,configFileObject,sectionNameStr) \
00319         { configFileObject.write(sectionNameStr,#variableName,variableName); }
00320 
00321 #define MRPT_SAVE_CONFIG_VAR_DEGREES(variableName,configFileObject,sectionNameStr) \
00322         { configFileObject.write(sectionNameStr,#variableName, RAD2DEG(variableName)); }
00323 
00324 
00325         } // End of namespace
00326 } // end of namespace
00327 #endif



Page generated by Doxygen 1.7.3 for MRPT 0.9.4 SVN: at Sat Mar 26 06:16:28 UTC 2011