Homepage Demos Overview Downloads Tutorials Reference
Credits

config.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2003-2004  Etienne Lachance
00003 
00004 This library is free software; you can redistribute it and/or modify
00005 it under the terms of the GNU Lesser General Public License as
00006 published by the Free Software Foundation; either version 2.1 of the
00007 License, or (at your option) any later version.
00008 
00009 This library is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU Lesser General Public License for more details.
00013 
00014 You should have received a copy of the GNU Lesser General Public
00015 License along with this library; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 
00019 Report problems and direct all questions to:
00020 
00021 email: etienne.lachance@polytml.ca or richard.gourdeau@polymtl.ca
00022 
00023 -------------------------------------------------------------------------------
00024 Revision_history:
00025 
00026 2004/06/10: Etienne Lachance
00027     -Added doxygen documentation.
00028 
00029 2004/07/01: Ethan Tira-Thompson
00030     -Added support for newmat's use_namespace #define, using ROBOOP namespace
00031 
00032 2004/07/13: Ethan Tira-Thompson
00033     -Added a select_real and add_real function for type indepence of Real
00034     -Added functions to test for sections and parameters existance
00035 
00036 2004/07/23: Ethan Tira-Thompson
00037     -Fixed potentially uninitialized variables and some other warnings
00038 
00039 2004/09/01: Ethan Tira-Thompson
00040     -Added optional parameter to constructor so you can automatically read_conf
00041     -select_* functions are now const
00042 
00043 2005/04/08: Ethan Tira-Thompson
00044     -Switched data storage to STL map, replacing the previous O(n^2) config file
00045      parsing, now approx O(n lg n) (actually a little better - O((s*p) lg (s+p)))
00046 -------------------------------------------------------------------------------
00047 */
00048 
00049 /*! 
00050   @file config.cpp
00051   @brief Configuration class functions.
00052 */
00053 
00054 
00055 #include "config.h"
00056 #include <iostream>
00057 #include <iomanip>
00058 #include <fstream>
00059 #ifdef __WATCOMC__
00060 #include <strstrea.h>
00061 #else
00062 #include <sstream>
00063 #endif
00064 
00065 #ifdef use_namespace
00066 namespace ROBOOP {
00067   using namespace NEWMAT;
00068 #endif
00069   
00070 //! @brief RCS/CVS version.
00071 static const char rcsid[] __UNUSED__ = "$Id: config.cpp,v 1.11 2005/07/26 03:22:08 ejt Exp $";
00072 
00073 Config::Config(const string & filename_, bool doRead/*=false*/)
00074 //! @brief Constructor.
00075   : conf(), filename(filename_)
00076 {
00077    if(doRead)
00078       read_conf();
00079 }
00080 
00081 Config::Config(const Config & x)
00082 //! @brief Constructor.
00083   : conf(x.conf), filename(x.filename)
00084 {
00085 }
00086 
00087 Config & Config::operator=(const Config & x)
00088 //! @brief Overload = operator.
00089 {
00090    conf = x.conf;
00091    filename = x.filename;
00092    return *this;
00093 }
00094 
00095 short Config::read_conf()
00096 /*!
00097   @brief Read a configuration file.
00098 
00099   This function reads the configuration file specified in 
00100   the constructor parameter. The information is stored in the
00101   variable conf.
00102 
00103   A configuration file contains section(s) (between [ ]), and the 
00104   section(s) contains parameter(s) with there respective value(s). 
00105   The section and the parameter are always access via a string. Below 
00106   is an exemple: one section named PUMA560_mDH, and two parameters.
00107 
00108   [PUMA560_mDH]
00109   DH:         0
00110   dof:        6
00111 */
00112 {
00113    const char *ptr_filename = filename.c_str(); //transform string to *char
00114    std::ifstream inconffile(ptr_filename, std::ios::in);
00115 
00116    if(inconffile)
00117    {
00118       string temp;
00119       int tmpPos;
00120   map<string,string>* cursection=NULL;
00121   string parameter, value;
00122 #ifdef __WATCOMC__
00123       char tempo[256], tempo2[256];
00124       inconffile.getline(tempo,sizeof(tempo));
00125       temp = tempo;
00126 #else
00127       getline(inconffile, temp);
00128 #endif
00129 
00130       while( !inconffile.eof() )
00131       {
00132    // Is-it comment line?
00133          if(temp.substr(0,1) != "#")
00134          {
00135       // Is-it a section name?
00136             if(temp.substr(0,1) == "[") // [section]
00137             {
00138          // Search for the end of the section name and ignore the rest of the line.
00139          tmpPos = temp.find("]");
00140          if (tmpPos != (int)string::npos)
00141      {
00142        cursection = &conf[temp.substr(1, tmpPos-1)]; // remove []
00143             
00144        // Read the next line, it's should be a parameter.
00145 #ifdef __WATCOMC__
00146        inconffile.getline(tempo,sizeof(tempo));
00147        temp = tempo;
00148 #else
00149        getline(inconffile, temp);
00150 #endif
00151        // Be sure that is not another section name.
00152        while( (temp.substr(0,1) != "[") &&
00153         (!inconffile.eof()) )
00154          {
00155            if(temp.substr(0,1) != "#") // ignore comments
00156        {
00157          if(temp.find(":") != string::npos)
00158            {
00159            try{
00160 #ifdef __WATCOMC__
00161              istrstream inputString(tempo);
00162              inputString >> tempo2;
00163              parameter = tempo2;
00164              inputString >> tempo2;
00165              value = tempo2;
00166 #else
00167 //             while(foo) ;
00168 //             std::cout << "Config Da " << temp << std::endl;
00169              istringstream inputString(temp);
00170 //             std::cout << "Config Db " << temp << std::endl;
00171              inputString >> parameter >> value;
00172 #endif
00173 //             std::cout << "Config Dc" << std::endl;
00174              // Find ":" in parameter.
00175              tmpPos = parameter.find(":");
00176              if (tmpPos != (int)string::npos)
00177          // remove ":" a the end of parameter
00178          parameter = parameter.substr(0, tmpPos);
00179              else
00180          {
00181 #ifdef __WATCOMC__
00182            inputString >> tempo2;
00183            value = tempo2;
00184 #else
00185            inputString >> value;
00186 #endif
00187          }
00188              } catch(std::exception e) { std::cout << "caught " << e.what() << ' ' << parameter << ' ' << value << endl; }
00189            catch(...) { std::cout << "caught " << parameter << ' ' << value << endl; }
00190 
00191              // Add data to the config vector
00192             if(cursection==NULL)
00193                std::cout << "parameter without section: " << parameter << " == " << value << endl;
00194             else
00195            (*cursection)[parameter]=value;
00196            }
00197 
00198          // Read the next line.
00199 #ifdef __WATCOMC__
00200          inconffile.getline(tempo,sizeof(tempo));
00201          temp = tempo;
00202 #else
00203          getline(inconffile, temp);
00204 #endif
00205        }
00206            else
00207        {
00208          // Ignore comments and read the next line.
00209 #ifdef __WATCOMC__
00210          inconffile.getline(tempo,sizeof(tempo));
00211          temp = tempo;
00212 #else
00213          getline(inconffile, temp);
00214 #endif
00215        }
00216          }
00217      }
00218             }
00219          }
00220          if(temp.substr(0,1) != "[") {
00221 #ifdef __WATCOMC__
00222             inconffile.getline(tempo,sizeof(tempo));
00223             temp = tempo;
00224 #else
00225             getline(inconffile, temp);
00226 #endif
00227          }
00228       }
00229    }
00230    else
00231    {
00232       cerr << "Config::read_conf: can not open file " << filename.c_str() << endl;
00233       return CAN_NOT_OPEN_FILE;
00234    }
00235    return 0;
00236 }
00237 
00238 void Config::print()
00239 //! @brief Print the configuration data.
00240 {
00241   for(confdata_t::const_iterator it=conf.begin(); it!=conf.end(); ++it) {
00242     cout << '[' << it->first << "]\n";
00243     for(map<string,string>::const_iterator vit=it->second.begin(); vit!=it->second.end(); ++vit)
00244       cout << setw(15-vit->first.size()) << vit->first+":" << " " << vit->second << '\n';
00245   }
00246   cout << flush;
00247 }
00248 
00249 bool Config::section_exists(const string& section) const
00250 /*!
00251   @brief Test to see if a section exists
00252   @return true if @a section is found
00253 */
00254 {
00255   return conf.find(section)!=conf.end();
00256 }
00257 
00258 bool Config::parameter_exists(const string& section, const string& parameter) const
00259 /*!
00260   @brief Test to see if a parameter exists within a section
00261   @return true if @a parameter is found within @a section
00262 */
00263 {
00264   confdata_t::const_iterator it=conf.find(section);
00265   if(it==conf.end())
00266     return false;
00267   return it->second.find(parameter)!=it->second.end();
00268 }
00269 
00270 short Config::select_string(const string section, const string parameter, string & value) const
00271 /*!
00272   @brief Get a parameter data, of a certain section, into the string value.
00273   @return 0 or SECTION_OR_PARAMETER_DOES_NOT_EXIST if the data can not be found.
00274 */
00275 {
00276   confdata_t::const_iterator it=conf.find(section);
00277   if(it!=conf.end()) {
00278     map<string,string>::const_iterator vit=it->second.find(parameter);
00279     if(vit!=it->second.end()) {
00280       value=vit->second;
00281       return 0;
00282     }
00283   }
00284    value = "";
00285    cerr << "Config::select_string: section " << section.c_str() << " or parameter "
00286    << parameter.c_str() << " does not exist." << endl;
00287    return SECTION_OR_PARAMETER_DOES_NOT_EXIST;
00288 }
00289 
00290 short Config::select_bool(const string section, const string parameter, bool & value) const
00291 /*!
00292   @brief Get a parameter data, of a certain section, into the bool value.
00293   @return 0 or SECTION_OR_PARAMETER_DOES_NOT_EXIST if the data can not be found.
00294 */
00295 {
00296    string value_string;
00297    if(!select_string(section, parameter, value_string))
00298    {
00299 #ifdef __WATCOMC__
00300       char temp[256];
00301       strcpy(temp,value_string.c_str());
00302       istrstream istr(temp);
00303       value = istr;
00304 #else
00305       istringstream istr(value_string);
00306       istr >> value;
00307 #endif
00308       return 0;
00309    }
00310    cerr << "Config::select_bool: section " << section.c_str() << " or parameter "
00311    << parameter.c_str() << " does not exist" << endl;
00312    value = false;
00313    return SECTION_OR_PARAMETER_DOES_NOT_EXIST;
00314 }
00315 
00316 short Config::select_int(const string section, const string parameter, int & value) const
00317 /*!
00318   @brief Get a parameter data, of a certain section, into the int value.
00319   @return 0 or SECTION_OR_PARAMETER_DOES_NOT_EXIST if the data can not be found.
00320 */
00321 {
00322    string value_string;
00323    if(!select_string(section, parameter, value_string))
00324    {
00325 #ifdef __WATCOMC__
00326       char temp[256];
00327       strcpy(temp,value_string.c_str());
00328       istrstream istr(temp);
00329       istr >> value;
00330 #else
00331       istringstream istr(value_string);
00332       istr >> value;
00333 #endif
00334       return 0;
00335    }
00336    cerr << "Config::select_int: section " << section.c_str() << " or parameter "
00337    << parameter.c_str() << " does not exist" << endl;
00338    value = 0;
00339    return SECTION_OR_PARAMETER_DOES_NOT_EXIST;
00340 }
00341 
00342 short Config::select_short(const string section, const string parameter, short & value) const
00343 /*!
00344   @brief Get a parameter data, of a certain section, into the short value.
00345   @return 0 or SECTION_OR_PARAMETER_DOES_NOT_EXIST if the data can not be found.
00346 */
00347 {
00348    string value_string;
00349    if(!select_string(section, parameter, value_string))
00350    {
00351 #ifdef __WATCOMC__
00352       char temp[256];
00353       strcpy(temp,value_string.c_str());
00354       istrstream istr(temp);
00355       istr >> value;
00356 #else
00357       istringstream istr(value_string);
00358       istr >> value;
00359 #endif
00360       return 0;
00361    }
00362    cerr << "Config::select_short: section " << section.c_str() << " or parameter "
00363    << parameter.c_str() << " does not exist" << endl;
00364    value = 0;
00365    return SECTION_OR_PARAMETER_DOES_NOT_EXIST;
00366 }
00367 
00368 short Config::select_float(const string section, const string parameter, float & value) const
00369 /*!
00370   @brief Get a parameter data, of a certain section, into the float value.
00371   @return 0 or SECTION_OR_PARAMETER_DOES_NOT_EXIST if the data can not be found.
00372 */
00373 {
00374    string value_string;
00375    if(!select_string(section, parameter, value_string))
00376    {
00377 #ifdef __WATCOMC__
00378       char temp[256];
00379       strcpy(temp,value_string.c_str());
00380       istrstream istr(temp);
00381       istr >> value;
00382 #else
00383       istringstream istr(value_string);
00384       istr >> value;
00385 #endif
00386       return 0;
00387    }
00388    cerr << "Config::select_float: section " << section.c_str() << " or parameter "
00389    << parameter.c_str() << " does not exist" << endl;
00390    value = 0.0;
00391    return SECTION_OR_PARAMETER_DOES_NOT_EXIST;
00392 }
00393 
00394 short Config::select_double(const string section, const string parameter, double & value) const
00395 /*!
00396   @brief Get a parameter data, of a certain section, into the double value.
00397   @return 0 or SECTION_OR_PARAMETER_DOES_NOT_EXIST if the data can not be found.
00398 */
00399 {
00400    string value_string;
00401    if(!select_string(section, parameter, value_string))
00402    {
00403 #ifdef __WATCOMC__
00404       char temp[256];
00405       strcpy(temp,value_string.c_str());
00406       istrstream istr(temp);
00407       istr >> value;
00408 #else
00409       istringstream istr(value_string);
00410       istr >> value;
00411 #endif
00412       return 0;
00413    }
00414    cerr << "Config::select_double: section " << section.c_str() << " or parameter "
00415    << parameter.c_str() << " does not exist" << endl;
00416    value = 0.0;
00417    return SECTION_OR_PARAMETER_DOES_NOT_EXIST;
00418 }
00419 
00420 short Config::select_real(const string section, const string parameter, Real & value) const
00421 /*!
00422   @brief Get a parameter data, of a certain section, into the Real value.
00423   @return 0 or SECTION_OR_PARAMETER_DOES_NOT_EXIST if the data can not be found.
00424 */
00425 {
00426    string value_string;
00427    if(!select_string(section, parameter, value_string))
00428    {
00429 #ifdef __WATCOMC__
00430       char temp[256];
00431       strcpy(temp,value_string.c_str());
00432       istrstream istr(temp);
00433       istr >> value;
00434 #else
00435       istringstream istr(value_string);
00436       istr >> value;
00437 #endif
00438       return 0;
00439    }
00440    cerr << "Config::select_real: section " << section.c_str() << " or parameter "
00441    << parameter.c_str() << " does not exist" << endl;
00442    value = 0.0;
00443    return SECTION_OR_PARAMETER_DOES_NOT_EXIST;
00444 }
00445 
00446 short Config::write_conf(const string name, const string file_title,
00447                          const int space_between_column)
00448 /*!
00449   @brief Write the configuration information, contained in conf, on disk.
00450   @param name: Configuration file name.
00451   @param file_title: Title in the configuration file header.
00452   @param space_between_column: Number of blanks between : (of a parameter) and it's value.
00453 */
00454 {
00455    const char *ptr_filename = name.c_str(); //transform string to *char
00456    std::ofstream outconffile(ptr_filename, std::ios::out);
00457 
00458    if(outconffile)
00459    {                     // file header
00460       outconffile << "# ---------------------------------------------------" << endl;
00461       outconffile << "# " << file_title << endl;
00462       outconffile << "# ---------------------------------------------------" << endl;
00463       outconffile << endl;
00464 
00465     for(confdata_t::const_iterator it=conf.begin(); it!=conf.end(); ++it) {
00466       outconffile << '[' << it->first << "]\n";
00467       for(map<string,string>::const_iterator vit=it->second.begin(); vit!=it->second.end(); ++vit)
00468         outconffile << setw(space_between_column-vit->first.size()) << vit->first + ": " << vit->second << '\n';
00469     }
00470       return 0;
00471    }
00472    else
00473    {
00474       cerr << "Config::write_conf: can not create file " << name.c_str() << endl;
00475       return CAN_NOT_CREATE_FILE;
00476    }
00477 }
00478 
00479 void Config::add_string(const string section, const string parameter, const string value)
00480 /*!
00481   @brief Added the value(string) of the parameter in the section in the configuration data.
00482 
00483   The functions will added the parameter and the section if it does not already exist.
00484 */
00485 {
00486   conf[section][parameter]=value;
00487 }
00488 
00489 void Config::add_bool(const string section, const string parameter,
00490                       const bool value)
00491 /*!
00492   @brief Added the value (bool) of the parameter in the section in the configuration data.
00493 
00494   The functions use add_string by first converting the value (bool) in value (string) 
00495 */
00496 {
00497    string value_tmp;
00498 #ifdef __WATCOMC__
00499    ostrstream ostr;
00500 #else
00501    ostringstream ostr;
00502 #endif
00503    ostr << value;
00504    value_tmp = ostr.str();
00505 
00506    add_string(section, parameter, value_tmp);
00507 }
00508 
00509 void Config::add_int(const string section, const string parameter,
00510                      const int value)
00511 /*!
00512   @brief Added the value (int) of the parameter in the section in the configuration data.
00513 
00514   The functions use add_string by first converting the value (int) in value (string) 
00515 */
00516 {
00517    string value_tmp;
00518 #ifdef __WATCOMC__
00519    ostrstream ostr;
00520 #else
00521    ostringstream ostr;
00522 #endif
00523    ostr << value;
00524    value_tmp = ostr.str();
00525 
00526    add_string(section, parameter, value_tmp);
00527 }
00528 
00529 void Config::add_float(const string section, const string parameter,
00530            const float value)
00531 /*!
00532   @brief Added the value (float) of the parameter in the section in the configuration data.
00533 
00534   The functions use add_string by first converting the value (float) in value (string) 
00535 */
00536 {
00537    string value_tmp;
00538 #ifdef __WATCOMC__
00539    ostrstream ostr;
00540 #else
00541    ostringstream ostr;
00542 #endif
00543 #ifdef _MSC_VER  
00544    ostr << value; // need to be fixed !
00545 #else
00546    ostr << setprecision(13) << value;
00547 #endif
00548    value_tmp = ostr.str();
00549 
00550    add_string(section, parameter, value_tmp);
00551 }
00552 
00553 void Config::add_double(const string section, const string parameter,
00554                         const double value)
00555 /*!
00556   @brief Added the value (double) of the parameter in the section in the configuration data.
00557 
00558   The functions use add_string by first converting the value (double) in value (string) 
00559 */
00560 {
00561    string value_tmp;
00562 #ifdef __WATCOMC__
00563    ostrstream ostr;
00564 #else
00565    ostringstream ostr;
00566 #endif
00567 #ifdef _MSC_VER  
00568    ostr << value; // need to be fixed !
00569 #else
00570    ostr << setprecision(13) << value;
00571 #endif
00572    value_tmp = ostr.str();
00573 
00574    add_string(section, parameter, value_tmp);
00575 }
00576 
00577 void Config::add_real(const string section, const string parameter,
00578                         const Real value)
00579 /*!
00580   @brief Added the value (Real) of the parameter in the section in the configuration data.
00581 
00582   The functions use add_string by first converting the value (Real) in value (string) 
00583 */
00584 {
00585    string value_tmp;
00586 #ifdef __WATCOMC__
00587    ostrstream ostr;
00588 #else
00589    ostringstream ostr;
00590 #endif
00591 #ifdef _MSC_VER  
00592    ostr << value; // need to be fixed !
00593 #else
00594    ostr << setprecision(13) << value;
00595 #endif
00596    value_tmp = ostr.str();
00597 
00598    add_string(section, parameter, value_tmp);
00599 }
00600 
00601 
00602 #ifdef use_namespace
00603 }
00604 #endif

ROBOOP v1.21a
Generated Tue Aug 16 16:32:14 2005 by Doxygen 1.4.4