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://www.mrpt.org/                                |
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                  * \ingroup mrpt_base_grp
00046           */
00047         class BASE_IMPEXP CConfigFileBase
00048         {
00049         protected:
00050                 /** A virtual method to write a generic string.
00051                   */
00052                 virtual void  writeString(const std::string &section,const std::string &name, const std::string &str) = 0;
00053 
00054                 /** A virtual method to read a generic string.
00055          * \exception std::exception If the key name is not found and "failIfNotFound" is true. Otherwise the "defaultValue" is returned.
00056                  */
00057                 virtual std::string  readString(
00058             const std::string &section,
00059             const std::string &name,
00060             const std::string &defaultStr,
00061             bool failIfNotFound = false) const = 0;
00062 
00063         public:
00064         /** Virtual destructor...
00065          */
00066          virtual ~CConfigFileBase()
00067          {
00068          }
00069 
00070                 /** Returns a list with all the section names.
00071                   */
00072                 virtual void getAllSections( vector_string      &sections ) const = 0 ;
00073 
00074                 /** Returs a list with all the keys into a section.
00075                   */
00076                 virtual void getAllKeys( const std::string section, vector_string       &keys ) const = 0;
00077 
00078                 /** Checks if a given section exists (name is case insensitive) */
00079                 bool sectionExists( const std::string &section_name) const;
00080 
00081                 /** Save a configuration parameter of type "double"
00082                  */
00083                 void  write(const std::string &section, const std::string &name, double value);
00084 
00085                 /** Save a configuration parameter of type "float"
00086                  */
00087                 void  write(const std::string &section, const std::string &name, float value);
00088 
00089                 /** Save a configuration parameter of type "int"
00090                  */
00091                 void  write(const std::string &section, const std::string &name, int value);
00092 
00093                 /** Save a configuration parameter of type "unsigned int"
00094                  */
00095                 void  write(const std::string &section, const std::string &name, unsigned int value);
00096 
00097 #if MRPT_WORD_SIZE>32
00098                 /** Save a configuration parameter of type "size_t"
00099                  */
00100                 void  write(const std::string &section, const std::string &name, size_t value);
00101 #endif
00102 
00103                 /** Save a configuration parameter of type "string"
00104                  */
00105                 void  write(const std::string &section, const std::string &name, const std::string &value);
00106 
00107                 /** Save a configuration parameter of type "std::vector<int>"
00108                  */
00109                 void  write(const std::string &section, const std::string &name, const std::vector<int> &value);
00110 
00111                 /** Save a configuration parameter of type "std::vector<unsigned int>"
00112                  */
00113                 void  write(const std::string &section, const std::string &name, const std::vector<unsigned int> &value);
00114 
00115                 /** Save a configuration parameter of type "std::vector<float>"
00116                  */
00117                 void  write(const std::string &section, const std::string &name, const std::vector<float> &value);
00118 
00119                 /** Save a configuration parameter of type "std::vector<double>"
00120                  */
00121                 void  write(const std::string &section, const std::string &name, const std::vector<double> &value);
00122 
00123                 /** Save a configuration parameter of type "std::vector<bool>"
00124                  */
00125                 void  write(const std::string &section, const std::string &name, const std::vector<bool> &value);
00126 
00127                 /** Reads a configuration parameter of type "double"
00128          * \exception std::exception If the key name is not found and "failIfNotFound" is true. Otherwise the "defaultValue" is returned.
00129                  */
00130                 double  read_double(const std::string &section, const std::string &name, double defaultValue, bool failIfNotFound = false) const;
00131 
00132                 /** Reads a configuration parameter of type "float"
00133          * \exception std::exception If the key name is not found and "failIfNotFound" is true. Otherwise the "defaultValue" is returned.
00134                  */
00135                 float  read_float(const std::string &section, const std::string &name, float defaultValue, bool failIfNotFound = false) const;
00136 
00137                 /** Reads a configuration parameter of type "bool", codified as "1"/"0" or "true"/"false" or "yes"/"no" for true/false, repectively.
00138          * \exception std::exception If the key name is not found and "failIfNotFound" is true. Otherwise the "defaultValue" is returned.
00139                  */
00140                 bool  read_bool(const std::string &section, const std::string &name, bool defaultValue, bool failIfNotFound = false) const;
00141 
00142                 /** Reads a configuration parameter of type "int"
00143          * \exception std::exception If the key name is not found and "failIfNotFound" is true. Otherwise the "defaultValue" is returned.
00144                  */
00145                 int  read_int(const std::string &section, const std::string &name, int defaultValue, bool failIfNotFound = false) const;
00146 
00147                 /** 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"
00148          * \exception std::exception If the key name is not found and "failIfNotFound" is true. Otherwise the "defaultValue" is returned.
00149                  */
00150                 uint64_t read_uint64_t(const std::string &section, const std::string &name, uint64_t defaultValue, bool failIfNotFound = false ) const;
00151 
00152                 /** Reads a configuration parameter of type "string"
00153          * \exception std::exception If the key name is not found and "failIfNotFound" is true. Otherwise the "defaultValue" is returned.
00154                  */
00155                 std::string  read_string(const std::string &section, const std::string &name, const std::string &defaultValue, bool failIfNotFound = false) const;
00156 
00157                 /** 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)
00158          * \exception std::exception If the key name is not found and "failIfNotFound" is true. Otherwise the "defaultValue" is returned.
00159                  */
00160                 std::string  read_string_first_word(const std::string &section, const std::string &name, const std::string &defaultValue, bool failIfNotFound = false) const;
00161 
00162                 /** Reads a configuration parameter of type vector, stored in the file as a string: "[v1 v2 v3 ... ]", where spaces could also be commas.
00163          * \exception std::exception If the key name is not found and "failIfNotFound" is true. Otherwise the "defaultValue" is returned.
00164                  */
00165                 template <class VECTOR_TYPE>
00166                 void  read_vector(
00167                         const std::string  & section,
00168                         const std::string  & name,
00169                         const VECTOR_TYPE  & defaultValue,
00170                         VECTOR_TYPE        & outValues,
00171                         bool                 failIfNotFound = false) const
00172                 {
00173                         std::string aux ( readString(section, name, "",failIfNotFound ) );
00174                         // Parse the text into a vector:
00175                         std::vector<std::string>        tokens;
00176                         mrpt::system::tokenize( aux,"[], \t",tokens);
00177 
00178                         if (tokens.size()==0)
00179                         {
00180                                 outValues = defaultValue;
00181                         }
00182                         else
00183                         {
00184                                 // Parse to numeric type:
00185                                 const size_t N = tokens.size();
00186                                 outValues.resize( N );
00187                                 for (size_t i=0;i<N;i++)
00188                                 {
00189                                         std::stringstream ss(tokens[i]);
00190                                         ss >> outValues[i];
00191                                 }
00192                         }
00193                 }
00194 
00195 
00196                 /** Reads a configuration parameter as a matrix written in a matlab-like format - for example: "[2 3 4 ; 7 8 9]"
00197                  *  This template method can be instantiated for matrices of the types: int, long, unsinged int, unsigned long, float, double, long double
00198          * \exception std::exception If the key name is not found and "failIfNotFound" is true. Otherwise the "defaultValue" is returned.
00199                  */
00200                  template <class MATRIX_TYPE>
00201                  void read_matrix(
00202                         const std::string                       &section,
00203                         const std::string                       &name,
00204                         MATRIX_TYPE     &outMatrix,
00205                         const MATRIX_TYPE &defaultMatrix = MATRIX_TYPE(),
00206                         bool failIfNotFound = false ) const
00207                 {
00208                         std::string aux = readString(section, name, "",failIfNotFound );
00209                         if (aux.empty())
00210                                 outMatrix = defaultMatrix;
00211                         else
00212                         {
00213                                 // Parse the text into a vector:
00214                                 if (!outMatrix.fromMatlabStringFormat(aux))
00215                                         THROW_EXCEPTION_CUSTOM_MSG1("Error parsing matrix: '%s'",aux.c_str())
00216                         }
00217                 }
00218 
00219                 /** Reads an "enum" value, where the value in the config file can be either a numerical value or the symbolic name, for example:
00220                   *   In the code:
00221                   *  \code
00222                   *    enum my_type_t { type_foo=0, type_bar };
00223                   *  \endcode
00224                   *  In the config file:
00225                   *  \code
00226                   *    [section]
00227                   *    type   = type_bar   // Use the symbolic name, or
00228                   *    type   = 1          // use the numerical value (both lines will be equivalent)
00229                   *  \endcode
00230                   *  Which can be loaded with:
00231                   *  \code
00232                   *    cfgfile.read_enum<my_type_t>("section","type", type_foo );
00233                   *  \endcode
00234                   *
00235                   *  \note For an enum type to work with this template it is required that it defines a specialization of mrpt::utils::TEnumType
00236                   */
00237                 template <typename ENUMTYPE>
00238                 ENUMTYPE read_enum(const std::string &section, const std::string &name, const ENUMTYPE &defaultValue, bool failIfNotFound = false) const
00239                 {
00240                         MRPT_START
00241                         const std::string sVal = read_string_first_word(section,name,"",failIfNotFound);
00242                         if (sVal.empty()) return defaultValue;
00243                         // Text or numeric value?
00244                         if (::isdigit(sVal[0]))
00245                         {       // Seems a number:
00246                                 return static_cast<ENUMTYPE>(::atoi(&sVal[0]));
00247                         }
00248                         else
00249                         {       // Name look-up:
00250                                 try {
00251                                 return mrpt::utils::TEnumType<ENUMTYPE>::name2value(sVal);
00252                                 } catch (std::exception &)
00253                                 {
00254                                         THROW_EXCEPTION(format("Invalid value '%s' for enum type while reading key='%s'.",sVal.c_str(),name.c_str()))
00255                                 }
00256                         }
00257                         MRPT_END
00258                 }
00259 
00260 
00261         }; // End of class def.
00262 
00263         /** 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.
00264           *  The variableType must be the suffix of "read_XXX" functions, i.e. int, bool,...
00265           */
00266 #define MRPT_LOAD_CONFIG_VAR(variableName,variableType,configFileObject,sectionNameStr) \
00267         { variableName = configFileObject.read_##variableType(sectionNameStr,#variableName,variableName); }
00268 
00269         /** Loads a float variable, stored as radians but entered in the INI-file as degrees:
00270           */
00271 #define MRPT_LOAD_CONFIG_VAR_DEGREES(variableName,configFileObject,sectionNameStr) \
00272         { variableName = DEG2RAD( configFileObject.read_float(sectionNameStr,#variableName, RAD2DEG(variableName)) ); }
00273 
00274 #define MRPT_LOAD_CONFIG_VAR_CAST(variableName,variableType,variableTypeCast,configFileObject,sectionNameStr) \
00275         { variableName = static_cast<variableTypeCast>(configFileObject.read_##variableType(sectionNameStr,#variableName,variableName)); }
00276 
00277 
00278 #define MRPT_LOAD_HERE_CONFIG_VAR(variableName,variableType,targetVariable,configFileObject,sectionNameStr) \
00279                 targetVariable = configFileObject.read_##variableType(sectionNameStr,#variableName,targetVariable,false);
00280 
00281 #define MRPT_LOAD_HERE_CONFIG_VAR_NO_DEFAULT(variableName,variableType,targetVariable,configFileObject,sectionNameStr) \
00282         { try { \
00283                 targetVariable = configFileObject.read_##variableType(sectionNameStr,#variableName,targetVariable,true); \
00284     } catch (std::exception &) \
00285     { \
00286                 THROW_EXCEPTION( format( "Value for '%s' not found in config file", static_cast<const char*>(#variableName ) )); \
00287         } }\
00288 
00289 
00290 #define MRPT_LOAD_CONFIG_VAR_NO_DEFAULT(variableName,variableType,configFileObject,sectionNameStr) \
00291         { try { \
00292                 variableName = configFileObject.read_##variableType(sectionNameStr,#variableName,variableName,true); \
00293     } catch (std::exception &) \
00294     { \
00295                 THROW_EXCEPTION( format( "Value for '%s' not found in config file", static_cast<const char*>(#variableName ) )); \
00296         } }\
00297 
00298 #define MRPT_LOAD_CONFIG_VAR_CAST_NO_DEFAULT(variableName,variableType,variableTypeCast,configFileObject,sectionNameStr) \
00299         { try { \
00300                 variableName = static_cast<variableTypeCast>(configFileObject.read_##variableType(sectionNameStr,#variableName,variableName,true)); \
00301     } catch (std::exception &) \
00302     { \
00303                 THROW_EXCEPTION( format( "Value for '%s' not found in config file", static_cast<const char*>(#variableName ) )); \
00304         } }\
00305 
00306 
00307 #define MRPT_LOAD_HERE_CONFIG_VAR_CAST(variableName,variableType,variableTypeCast,targetVariable,configFileObject,sectionNameStr) \
00308                 targetVariable = static_cast<variableTypeCast>(configFileObject.read_##variableType(sectionNameStr,#variableName,targetVariable));
00309 
00310 #define MRPT_LOAD_HERE_CONFIG_VAR_CAST_NO_DEFAULT(variableName,variableType,variableTypeCast,targetVariable,configFileObject,sectionNameStr) \
00311         { try { \
00312                 targetVariable = static_cast<variableTypeCast>(configFileObject.read_##variableType(sectionNameStr,#variableName,targetVariable,true)); \
00313     } catch (std::exception &) \
00314     { \
00315                 THROW_EXCEPTION( format( "Value for '%s' not found in config file", static_cast<const char*>(#variableName ) )); \
00316         } }\
00317 
00318 
00319 #define MRPT_SAVE_CONFIG_VAR(variableName,configFileObject,sectionNameStr) \
00320         { configFileObject.write(sectionNameStr,#variableName,variableName); }
00321 
00322 #define MRPT_SAVE_CONFIG_VAR_DEGREES(variableName,configFileObject,sectionNameStr) \
00323         { configFileObject.write(sectionNameStr,#variableName, RAD2DEG(variableName)); }
00324 
00325 
00326         } // End of namespace
00327 } // end of namespace
00328 #endif



Page generated by Doxygen 1.7.5 for MRPT 0.9.5 SVN: at Thu Oct 13 21:25:36 UTC 2011