Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
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 using namespace std;
00066 
00067 #ifdef use_namespace
00068 namespace ROBOOP {
00069   using namespace NEWMAT;
00070 #endif
00071   
00072 //! @brief RCS/CVS version.
00073 static const char rcsid[] __UNUSED__ = "$Id: config.cpp,v 1.14 2007/11/11 23:57:24 ejt Exp $";
00074 
00075 Config::Config(const string & filename_, bool doRead/*=false*/)
00076 //! @brief Constructor.
00077   : conf(), filename(filename_)
00078 {
00079    if(doRead)
00080       read_conf();
00081 }
00082 
00083 Config::Config(const Config & x)
00084 //! @brief Constructor.
00085   : conf(x.conf), filename(x.filename)
00086 {
00087 }
00088 
00089 Config & Config::operator=(const Config & x)
00090 //! @brief Overload = operator.
00091 {
00092    conf = x.conf;
00093    filename = x.filename;
00094    return *this;
00095 }
00096 
00097 short Config::read_conf()
00098 /*!
00099   @brief Read a configuration file.
00100 
00101   This function reads the configuration file specified in 
00102   the constructor parameter. The information is stored in the
00103   variable conf.
00104 
00105   A configuration file contains section(s) (between [ ]), and the 
00106   section(s) contains parameter(s) with there respective value(s). 
00107   The section and the parameter are always access via a string. Below 
00108   is an exemple: one section named PUMA560_mDH, and two parameters.
00109 
00110   [PUMA560_mDH]
00111   DH:         0
00112   dof:        6
00113 */
00114 {
00115    const char *ptr_filename = filename.c_str(); //transform string to *char
00116    std::ifstream inconffile(ptr_filename, std::ios::in);
00117 
00118    string temp;
00119 #ifdef __WATCOMC__
00120    char tempo[256], tempo2[256];
00121    inconffile.getline(tempo,sizeof(tempo));
00122    temp = tempo;
00123 #else
00124    getline(inconffile, temp);
00125 #endif
00126    if(inconffile)
00127    {
00128       int tmpPos;
00129       map<string,string>* cursection=NULL;
00130       string parameter, value;
00131 
00132       while( inconffile )
00133       {
00134    // Is-it comment line?
00135          if(temp[0] != '#')
00136          {
00137       // Is-it a section name?
00138             if(temp[0] == '[') // [section]
00139             {
00140          // Search for the end of the section name and ignore the rest of the line.
00141          tmpPos = temp.find("]");
00142          if (tmpPos != (int)string::npos)
00143      {
00144        cursection = &conf[temp.substr(1, tmpPos-1)]; // remove []
00145             
00146        // Read the next line, it's should be a parameter.
00147 #ifdef __WATCOMC__
00148        inconffile.getline(tempo,sizeof(tempo));
00149        temp = tempo;
00150 #else
00151        getline(inconffile, temp);
00152 #endif
00153        // Be sure that is not another section name.
00154        while( (temp[0] != '[') &&
00155         (!inconffile.eof()) )
00156          {
00157            if(temp[0] != '#') // ignore comments
00158        {
00159          if(temp.find(":") != string::npos)
00160            {
00161            try{
00162 #ifdef __WATCOMC__
00163              istrstream inputString(tempo);
00164              inputString >> tempo2;
00165              parameter = tempo2;
00166              inputString >> tempo2;
00167              value = tempo2;
00168 #else
00169 //             while(foo) ;
00170 //             std::cout << "Config Da " << temp << std::endl;
00171              istringstream inputString(temp);
00172 //             std::cout << "Config Db " << temp << std::endl;
00173              inputString >> parameter >> value;
00174 #endif
00175 //             std::cout << "Config Dc" << std::endl;
00176              // Find ":" in parameter.
00177              tmpPos = parameter.find(":");
00178              if (tmpPos != (int)string::npos)
00179          // remove ":" a the end of parameter
00180          parameter = parameter.erase(tmpPos);
00181              else
00182          {
00183 #ifdef __WATCOMC__
00184            inputString >> tempo2;
00185            value = tempo2;
00186 #else
00187            inputString >> value;
00188 #endif
00189          }
00190              } catch(std::exception e) { std::cout << "caught " << e.what() << ' ' << parameter << ' ' << value << endl; }
00191            catch(...) { std::cout << "caught " << parameter << ' ' << value << endl; }
00192 
00193              // Add data to the config vector
00194             if(cursection==NULL)
00195                std::cout << "parameter without section: " << parameter << " == " << value << endl;
00196             else
00197            (*cursection)[parameter]=value;
00198            }
00199 
00200          // Read the next line.
00201 #ifdef __WATCOMC__
00202          inconffile.getline(tempo,sizeof(tempo));
00203          temp = tempo;
00204 #else
00205          getline(inconffile, temp);
00206 #endif
00207        }
00208            else
00209        {
00210          // Ignore comments and read the next line.
00211 #ifdef __WATCOMC__
00212          inconffile.getline(tempo,sizeof(tempo));
00213          temp = tempo;
00214 #else
00215          getline(inconffile, temp);
00216 #endif
00217        }
00218          }
00219      }
00220             }
00221          }
00222          if(temp.substr(0,1) != "[") {
00223 #ifdef __WATCOMC__
00224             inconffile.getline(tempo,sizeof(tempo));
00225             temp = tempo;
00226 #else
00227             getline(inconffile, temp);
00228 #endif
00229          }
00230       }
00231    }
00232    else
00233    {
00234       cerr << "Config::read_conf: can not open file " << filename.c_str() << endl;
00235       return CAN_NOT_OPEN_FILE;
00236    }
00237    return 0;
00238 }
00239 
00240 void Config::print()
00241 //! @brief Print the configuration data.
00242 {
00243   for(confdata_t::const_iterator it=conf.begin(); it!=conf.end(); ++it) {
00244     cout << '[' << it->first << "]\n";
00245     for(map<string,string>::const_iterator vit=it->second.begin(); vit!=it->second.end(); ++vit)
00246       cout << setw(15-vit->first.size()) << vit->first+":" << " " << vit->second << '\n';
00247   }
00248   cout << flush;
00249 }
00250 
00251 bool Config::section_exists(const string& section) const
00252 /*!
00253   @brief Test to see if a section exists
00254   @return true if @a section is found
00255 */
00256 {
00257   return conf.find(section)!=conf.end();
00258 }
00259 
00260 bool Config::parameter_exists(const string& section, const string& parameter) const
00261 /*!
00262   @brief Test to see if a parameter exists within a section
00263   @return true if @a parameter is found within @a section
00264 */
00265 {
00266   confdata_t::const_iterator it=conf.find(section);
00267   if(it==conf.end())
00268     return false;
00269   return it->second.find(parameter)!=it->second.end();
00270 }
00271 
00272 short Config::select_string(const string section, const string parameter, string & value) const
00273 /*!
00274   @brief Get a parameter data, of a certain section, into the string value.
00275   @return 0 or SECTION_OR_PARAMETER_DOES_NOT_EXIST if the data can not be found.
00276 */
00277 {
00278   confdata_t::const_iterator it=conf.find(section);
00279   if(it!=conf.end()) {
00280     map<string,string>::const_iterator vit=it->second.find(parameter);
00281     if(vit!=it->second.end()) {
00282       value=vit->second;
00283       return 0;
00284     }
00285   }
00286    value = "";
00287    cerr << "Config::select_string: section " << section.c_str() << " or parameter "
00288    << parameter.c_str() << " does not exist." << endl;
00289    return SECTION_OR_PARAMETER_DOES_NOT_EXIST;
00290 }
00291 
00292 short Config::select_bool(const string section, const string parameter, bool & value) const
00293 /*!
00294   @brief Get a parameter data, of a certain section, into the bool value.
00295   @return 0 or SECTION_OR_PARAMETER_DOES_NOT_EXIST if the data can not be found.
00296 */
00297 {
00298    string value_string;
00299    if(!select_string(section, parameter, value_string))
00300    {
00301 #ifdef __WATCOMC__
00302       char temp[256];
00303       strcpy(temp,value_string.c_str());
00304       istrstream istr(temp);
00305       value = istr;
00306 #else
00307       istringstream istr(value_string);
00308       istr >> value;
00309 #endif
00310       return 0;
00311    }
00312    cerr << "Config::select_bool: section " << section.c_str() << " or parameter "
00313    << parameter.c_str() << " does not exist" << endl;
00314    value = false;
00315    return SECTION_OR_PARAMETER_DOES_NOT_EXIST;
00316 }
00317 
00318 short Config::select_int(const string section, const string parameter, int & value) const
00319 /*!
00320   @brief Get a parameter data, of a certain section, into the int value.
00321   @return 0 or SECTION_OR_PARAMETER_DOES_NOT_EXIST if the data can not be found.
00322 */
00323 {
00324    string value_string;
00325    if(!select_string(section, parameter, value_string))
00326    {
00327 #ifdef __WATCOMC__
00328       char temp[256];
00329       strcpy(temp,value_string.c_str());
00330       istrstream istr(temp);
00331       istr >> value;
00332 #else
00333       istringstream istr(value_string);
00334       istr >> value;
00335 #endif
00336       return 0;
00337    }
00338    cerr << "Config::select_int: section " << section.c_str() << " or parameter "
00339    << parameter.c_str() << " does not exist" << endl;
00340    value = 0;
00341    return SECTION_OR_PARAMETER_DOES_NOT_EXIST;
00342 }
00343 
00344 short Config::select_short(const string section, const string parameter, short & value) const
00345 /*!
00346   @brief Get a parameter data, of a certain section, into the short value.
00347   @return 0 or SECTION_OR_PARAMETER_DOES_NOT_EXIST if the data can not be found.
00348 */
00349 {
00350    string value_string;
00351    if(!select_string(section, parameter, value_string))
00352    {
00353 #ifdef __WATCOMC__
00354       char temp[256];
00355       strcpy(temp,value_string.c_str());
00356       istrstream istr(temp);
00357       istr >> value;
00358 #else
00359       istringstream istr(value_string);
00360       istr >> value;
00361 #endif
00362       return 0;
00363    }
00364    cerr << "Config::select_short: section " << section.c_str() << " or parameter "
00365    << parameter.c_str() << " does not exist" << endl;
00366    value = 0;
00367    return SECTION_OR_PARAMETER_DOES_NOT_EXIST;
00368 }
00369 
00370 short Config::select_float(const string section, const string parameter, float & value) const
00371 /*!
00372   @brief Get a parameter data, of a certain section, into the float value.
00373   @return 0 or SECTION_OR_PARAMETER_DOES_NOT_EXIST if the data can not be found.
00374 */
00375 {
00376    string value_string;
00377    if(!select_string(section, parameter, value_string))
00378    {
00379 #ifdef __WATCOMC__
00380       char temp[256];
00381       strcpy(temp,value_string.c_str());
00382       istrstream istr(temp);
00383       istr >> value;
00384 #else
00385       istringstream istr(value_string);
00386       istr >> value;
00387 #endif
00388       return 0;
00389    }
00390    cerr << "Config::select_float: section " << section.c_str() << " or parameter "
00391    << parameter.c_str() << " does not exist" << endl;
00392    value = 0.0;
00393    return SECTION_OR_PARAMETER_DOES_NOT_EXIST;
00394 }
00395 
00396 short Config::select_double(const string section, const string parameter, double & value) const
00397 /*!
00398   @brief Get a parameter data, of a certain section, into the double value.
00399   @return 0 or SECTION_OR_PARAMETER_DOES_NOT_EXIST if the data can not be found.
00400 */
00401 {
00402    string value_string;
00403    if(!select_string(section, parameter, value_string))
00404    {
00405 #ifdef __WATCOMC__
00406       char temp[256];
00407       strcpy(temp,value_string.c_str());
00408       istrstream istr(temp);
00409       istr >> value;
00410 #else
00411       istringstream istr(value_string);
00412       istr >> value;
00413 #endif
00414       return 0;
00415    }
00416    cerr << "Config::select_double: section " << section.c_str() << " or parameter "
00417    << parameter.c_str() << " does not exist" << endl;
00418    value = 0.0;
00419    return SECTION_OR_PARAMETER_DOES_NOT_EXIST;
00420 }
00421 
00422 short Config::select_real(const string section, const string parameter, Real & value) const
00423 /*!
00424   @brief Get a parameter data, of a certain section, into the Real value.
00425   @return 0 or SECTION_OR_PARAMETER_DOES_NOT_EXIST if the data can not be found.
00426 */
00427 {
00428    string value_string;
00429    if(!select_string(section, parameter, value_string))
00430    {
00431 #ifdef __WATCOMC__
00432       char temp[256];
00433       strcpy(temp,value_string.c_str());
00434       istrstream istr(temp);
00435       istr >> value;
00436 #else
00437       istringstream istr(value_string);
00438       istr >> value;
00439 #endif
00440       return 0;
00441    }
00442    cerr << "Config::select_real: section " << section.c_str() << " or parameter "
00443    << parameter.c_str() << " does not exist" << endl;
00444    value = 0.0;
00445    return SECTION_OR_PARAMETER_DOES_NOT_EXIST;
00446 }
00447 
00448 short Config::write_conf(const string name, const string file_title,
00449                          const int space_between_column)
00450 /*!
00451   @brief Write the configuration information, contained in conf, on disk.
00452   @param name: Configuration file name.
00453   @param file_title: Title in the configuration file header.
00454   @param space_between_column: Number of blanks between : (of a parameter) and it's value.
00455 */
00456 {
00457    const char *ptr_filename = name.c_str(); //transform string to *char
00458    std::ofstream outconffile(ptr_filename, std::ios::out);
00459 
00460    if(outconffile)
00461    {                     // file header
00462       outconffile << "# ---------------------------------------------------" << endl;
00463       outconffile << "# " << file_title << endl;
00464       outconffile << "# ---------------------------------------------------" << endl;
00465       outconffile << endl;
00466 
00467     for(confdata_t::const_iterator it=conf.begin(); it!=conf.end(); ++it) {
00468       outconffile << '[' << it->first << "]\n";
00469       for(map<string,string>::const_iterator vit=it->second.begin(); vit!=it->second.end(); ++vit)
00470         outconffile << setw(space_between_column-vit->first.size()) << vit->first + ": " << vit->second << '\n';
00471     }
00472       return 0;
00473    }
00474    else
00475    {
00476       cerr << "Config::write_conf: can not create file " << name.c_str() << endl;
00477       return CAN_NOT_CREATE_FILE;
00478    }
00479 }
00480 
00481 void Config::add_string(const string section, const string parameter, const string value)
00482 /*!
00483   @brief Added the value(string) of the parameter in the section in the configuration data.
00484 
00485   The functions will added the parameter and the section if it does not already exist.
00486 */
00487 {
00488   conf[section][parameter]=value;
00489 }
00490 
00491 void Config::add_bool(const string section, const string parameter,
00492                       const bool value)
00493 /*!
00494   @brief Added the value (bool) of the parameter in the section in the configuration data.
00495 
00496   The functions use add_string by first converting the value (bool) in value (string) 
00497 */
00498 {
00499    string value_tmp;
00500 #ifdef __WATCOMC__
00501    ostrstream ostr;
00502 #else
00503    ostringstream ostr;
00504 #endif
00505    ostr << value;
00506    value_tmp = ostr.str();
00507 
00508    add_string(section, parameter, value_tmp);
00509 }
00510 
00511 void Config::add_int(const string section, const string parameter,
00512                      const int value)
00513 /*!
00514   @brief Added the value (int) of the parameter in the section in the configuration data.
00515 
00516   The functions use add_string by first converting the value (int) in value (string) 
00517 */
00518 {
00519    string value_tmp;
00520 #ifdef __WATCOMC__
00521    ostrstream ostr;
00522 #else
00523    ostringstream ostr;
00524 #endif
00525    ostr << value;
00526    value_tmp = ostr.str();
00527 
00528    add_string(section, parameter, value_tmp);
00529 }
00530 
00531 void Config::add_float(const string section, const string parameter,
00532            const float value)
00533 /*!
00534   @brief Added the value (float) of the parameter in the section in the configuration data.
00535 
00536   The functions use add_string by first converting the value (float) in value (string) 
00537 */
00538 {
00539    string value_tmp;
00540 #ifdef __WATCOMC__
00541    ostrstream ostr;
00542 #else
00543    ostringstream ostr;
00544 #endif
00545 #ifdef _MSC_VER  
00546    ostr << value; // need to be fixed !
00547 #else
00548    ostr << setprecision(13) << value;
00549 #endif
00550    value_tmp = ostr.str();
00551 
00552    add_string(section, parameter, value_tmp);
00553 }
00554 
00555 void Config::add_double(const string section, const string parameter,
00556                         const double value)
00557 /*!
00558   @brief Added the value (double) of the parameter in the section in the configuration data.
00559 
00560   The functions use add_string by first converting the value (double) in value (string) 
00561 */
00562 {
00563    string value_tmp;
00564 #ifdef __WATCOMC__
00565    ostrstream ostr;
00566 #else
00567    ostringstream ostr;
00568 #endif
00569 #ifdef _MSC_VER  
00570    ostr << value; // need to be fixed !
00571 #else
00572    ostr << setprecision(13) << value;
00573 #endif
00574    value_tmp = ostr.str();
00575 
00576    add_string(section, parameter, value_tmp);
00577 }
00578 
00579 void Config::add_real(const string section, const string parameter,
00580                         const Real value)
00581 /*!
00582   @brief Added the value (Real) of the parameter in the section in the configuration data.
00583 
00584   The functions use add_string by first converting the value (Real) in value (string) 
00585 */
00586 {
00587    string value_tmp;
00588 #ifdef __WATCOMC__
00589    ostrstream ostr;
00590 #else
00591    ostringstream ostr;
00592 #endif
00593 #ifdef _MSC_VER  
00594    ostr << value; // need to be fixed !
00595 #else
00596    ostr << setprecision(13) << value;
00597 #endif
00598    value_tmp = ostr.str();
00599 
00600    add_string(section, parameter, value_tmp);
00601 }
00602 
00603 
00604 #ifdef use_namespace
00605 }
00606 #endif

ROBOOP v1.21a
Generated Thu Nov 22 00:51:28 2007 by Doxygen 1.5.4