INIFile.cc

00001 /*===========================================================================*\
00002  *                                                                           *
00003  *                              OpenFlipper                                  *
00004  *      Copyright (C) 2001-2009 by Computer Graphics Group, RWTH Aachen      *
00005  *                           www.openflipper.org                             *
00006  *                                                                           *
00007  *---------------------------------------------------------------------------*
00008  *  This file is part of OpenFlipper.                                        *
00009  *                                                                           *
00010  *  OpenFlipper is free software: you can redistribute it and/or modify      *
00011  *  it under the terms of the GNU Lesser General Public License as           *
00012  *  published by the Free Software Foundation, either version 3 of           *
00013  *  the License, or (at your option) any later version with the              *
00014  *  following exceptions:                                                    *
00015  *                                                                           *
00016  *  If other files instantiate templates or use macros                       *
00017  *  or inline functions from this file, or you compile this file and         *
00018  *  link it with other files to produce an executable, this file does        *
00019  *  not by itself cause the resulting executable to be covered by the        *
00020  *  GNU Lesser General Public License. This exception does not however       *
00021  *  invalidate any other reasons why the executable file might be            *
00022  *  covered by the GNU Lesser General Public License.                        *
00023  *                                                                           *
00024  *  OpenFlipper is distributed in the hope that it will be useful,           *
00025  *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
00026  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
00027  *  GNU Lesser General Public License for more details.                      *
00028  *                                                                           *
00029  *  You should have received a copy of the GNU LesserGeneral Public          *
00030  *  License along with OpenFlipper. If not,                                  *
00031  *  see <http://www.gnu.org/licenses/>.                                      *
00032  *                                                                           *
00033 \*===========================================================================*/
00034 
00035 /*===========================================================================*\
00036  *                                                                           *
00037  *   $Revision: 8520 $                                                         *
00038  *   $Author: moebius $                                                      *
00039  *   $Date: 2010-02-10 15:56:59 +0100 (Mi, 10. Feb 2010) $                   *
00040  *                                                                           *
00041 \*===========================================================================*/
00042 
00043 
00044 
00045 
00046 #include "INIFile.hh"
00047 
00048 //std include
00049 #include <fstream>
00050 #include <iostream>
00051 #include <functional>
00052 #include <sstream>
00053 #include <cstring>
00054 #include <cctype>
00055 //#include <ios>
00056 
00057 #include <QString>
00058 #include <QFile>
00059 #include <QTextStream>
00060 #include <QStringList>
00061 
00062 // -----------------------------------------------------------------------------
00063 
00064 INIFile::INIFile()
00065 {
00066   mf_isConnected = false;
00067 }
00068 
00069 
00070 // -----------------------------------------------------------------------------
00071 
00072 INIFile::~INIFile()
00073 {
00074   disconnect();
00075 }
00076 
00077 
00078 // -----------------------------------------------------------------------------
00079 
00080 bool INIFile::connect( const QString& _filename,
00081                        const bool _create )
00082 {
00083   QFile inputFile( _filename );
00084 
00085   if( is_connected() )
00086     disconnect();
00087 
00088   // open given file for reading
00089   if ( inputFile.exists() &&  inputFile.open(QIODevice::ReadOnly | QIODevice::Text) )  {
00090 
00091     // Successfull?
00092     m_filename = _filename;
00093 
00094     // try to parse the INI file
00095     mf_isConnected = parseFile( inputFile );
00096 
00097     inputFile.close();
00098 
00099   } else if( _create ) {
00100 
00101     // file does not exist yet, but user wants to create it.
00102     // therefore: try to create file
00103     QFile outputFile(_filename);
00104 
00105     if ( outputFile.open( QIODevice::Text |
00106                           QIODevice::WriteOnly |
00107                           QIODevice::Truncate ) )  {
00108 
00109       mf_isConnected = true;
00110       m_filename = _filename;
00111       outputFile.close();
00112 
00113     } else {
00114 
00115       std::cerr << "Unable to create File : " << std::endl;
00116       mf_isConnected = false;
00117 
00118     }
00119 
00120   } else {
00121     std::cerr << "Unable to open File : " << std::endl;
00122     mf_isConnected = false;
00123   }
00124 
00125   return mf_isConnected;
00126 }
00127 
00128 
00129 
00130 // -----------------------------------------------------------------------------
00131 
00132 void INIFile::disconnect()
00133 {
00134   writeFile();
00135   mf_isConnected = false;
00136 }
00137 
00138 
00139 // -----------------------------------------------------------------------------
00140 
00141 bool INIFile::parseFile( QFile & _inputStream )
00142 {
00143   QString line, section;
00144   bool inSection = false;
00145 
00146   // read file line by line
00147   while( !_inputStream.atEnd()  ) {
00148 
00149     // get new line
00150     QByteArray lineBuffer = _inputStream.readLine();
00151     line = QString(lineBuffer);
00152     line = line.trimmed();
00153 
00154     if( line.isEmpty() || line[ 0 ] == '#' )
00155       continue;
00156 
00157     // does line contain the start of a section?
00158     if( line[ 0 ] == '[' && line[ line.length()-1 ] == ']' ) {
00159 
00160       // yes
00161       section = line.mid( 1, line.length() - 2 );
00162       inSection = true;
00163 
00164     } else if( inSection ) {
00165       // try to split line into a key and a value
00166       QString key, value;
00167 
00168       int pos;
00169       pos = line.indexOf( '=' );
00170 
00171       if( pos != -1 )
00172       {
00173         key = line.mid( 0, pos );
00174         key = key.trimmed();
00175         value = line.mid( pos + 1, line.length() - 1 );
00176         value = value.trimmed();
00177 
00178         if( key.isEmpty() || value.isEmpty() )
00179             continue;
00180 
00181         // store value in string-map
00182         m_iniData[ section ][ key ] = value;
00183       }
00184 
00185     }
00186   }
00187 
00188   return true;
00189 }
00190 
00191 
00192 // -----------------------------------------------------------------------------
00193 
00194 
00195 bool INIFile::writeFile( void )
00196 {
00197   if( !mf_isConnected )
00198       return false;
00199 
00200   // open file for writing
00201   QFile outputFile(m_filename);
00202 
00203   if ( ! outputFile.open( QIODevice::WriteOnly ) )
00204     return false;
00205 
00206   QTextStream out(&outputFile);
00207 
00208   // file is open, start writing of data
00209   SectionMap::const_iterator sIter, sEnd;
00210   EntryMap::const_iterator eIter, eEnd;
00211 
00212   sEnd = m_iniData.end();
00213   for( sIter = m_iniData.begin(); sIter != sEnd; ++sIter ) {
00214     // write name of current section
00215     out << "[" << sIter->first << "]\n";
00216 
00217     eEnd = sIter->second.end();
00218     for( eIter = sIter->second.begin(); eIter != eEnd; ++eIter ) {
00219       out << eIter->first << "=";
00220       out << eIter->second;
00221       out << "\n";
00222     }
00223 
00224     out << "\n\n";
00225   }
00226 
00227   outputFile.close();
00228 
00229   return true;
00230 }
00231 
00232 
00233 
00234 // -----------------------------------------------------------------------------
00235 
00236 
00237 bool INIFile::section_exists( const QString & _section ) const
00238 {
00239   return( m_iniData.find( _section ) != m_iniData.end() );
00240 }
00241 
00242 
00243 // -----------------------------------------------------------------------------
00244 
00245 
00246 bool INIFile::entry_exists(const QString & _section, const QString & _key) const
00247 {
00248   static SectionMap::const_iterator mapIter;
00249 
00250   return( (mapIter = m_iniData.find( _section )) != m_iniData.end()
00251           && mapIter->second.find( _key ) != mapIter->second.end() );
00252 }
00253 
00254 
00255 // -----------------------------------------------------------------------------
00256 
00257 void INIFile::add_section( const QString & _sectionname )
00258 {
00259   if( m_iniData.find( _sectionname ) == m_iniData.end() )
00260       m_iniData[ _sectionname ] = EntryMap();
00261 }
00262 
00263 
00264 // -----------------------------------------------------------------------------
00265 
00266 
00267 void INIFile::add_entry( const QString & _section,
00268                          const QString & _key,
00269                          const QString & _value )
00270 {
00271   m_iniData[ _section ][ _key ] = _value;
00272 }
00273 
00274 
00275 // -----------------------------------------------------------------------------
00276 
00277 
00278 void INIFile::add_entry( const QString & _section,
00279                          const QString & _key,
00280                          const double & _value)
00281 {
00282   m_iniData[ _section ][ _key ] = QString::number( _value );
00283 }
00284 
00285 
00286 // -----------------------------------------------------------------------------
00287 
00288 
00289 void INIFile::add_entry( const QString & _section,
00290                          const QString & _key,
00291                          const float & _value)
00292 {
00293   m_iniData[ _section ][ _key ] = QString::number( _value );
00294 }
00295 
00296 
00297 // -----------------------------------------------------------------------------
00298 
00299 
00300 void INIFile::add_entry( const QString & _section,
00301                          const QString & _key ,
00302                          const int & _value)
00303 {
00304   m_iniData[ _section ][ _key ] = QString::number( _value );
00305 }
00306 
00307 
00308 // -----------------------------------------------------------------------------
00309 
00310 
00311 void INIFile::add_entry( const QString & _section,
00312                          const QString & _key ,
00313                          const unsigned int & _value)
00314 {
00315   m_iniData[ _section ][ _key ] = QString::number( _value );
00316 }
00317 
00318 
00319 // -----------------------------------------------------------------------------
00320 
00321 
00322 void INIFile::add_entry( const QString & _section,
00323                          const QString & _key ,
00324                          const bool & _value)
00325 {
00326   m_iniData[ _section ][ _key ] = (_value ? "true" : "false");
00327 }
00328 
00329 
00330 // -----------------------------------------------------------------------------
00331 
00332 
00333 void INIFile::add_entry( const QString & _section,
00334                          const QString & _key,
00335                          const std::vector<float> & _value)
00336 {
00337   QString list;
00338   std::vector<float>::const_iterator viter;
00339   for(viter = _value.begin();viter!=_value.end();++viter)
00340     list += QString::number( *viter ) + ";";
00341   m_iniData[ _section ][ _key ] = list;
00342 }
00343 
00344 
00345 // -----------------------------------------------------------------------------
00346 
00347 
00348 void INIFile::add_entry( const QString & _section,
00349                          const QString & _key,
00350                          const std::vector<double> & _value)
00351 {
00352   QString list;
00353   std::vector<double>::const_iterator viter;
00354   for(viter = _value.begin();viter!=_value.end();++viter)
00355     list += QString::number( *viter ) + ";";
00356   m_iniData[ _section ][ _key ] = list;
00357 }
00358 
00359 
00360 // -----------------------------------------------------------------------------
00361 
00362 void INIFile::add_entry( const QString & _section,
00363           const QString & _key,
00364           const std::vector<int> & _value)
00365 {
00366   QString list;
00367   std::vector<int>::const_iterator viter;
00368   for(viter = _value.begin();viter!=_value.end();++viter)
00369     list += QString::number( *viter ) + ";";
00370   m_iniData[ _section ][ _key ] = list;
00371 }
00372 
00373 // -----------------------------------------------------------------------------
00374 
00375 void INIFile::add_entry( const QString & _section,
00376           const QString & _key,
00377           const std::vector<QString> & _value)
00378 {
00379   QString list;
00380   std::vector<QString>::const_iterator viter;
00381   for(viter = _value.begin();viter!=_value.end();++viter) {
00382     list += *viter + ";";
00383   }
00384   m_iniData[ _section ][ _key ] = list;
00385 }
00386 
00387 // -----------------------------------------------------------------------------
00388 
00389 void INIFile::add_entry( const QString & _section,
00390           const QString & _key,
00391           const QStringList & _value)
00392 {
00393   QString list = _value.join(";");
00394   m_iniData[ _section ][ _key ] = list;
00395 }
00396 
00397 
00398 // -----------------------------------------------------------------------------
00399 
00400 void INIFile::delete_entry( const QString & _section, const QString & _key )
00401 {
00402   SectionMap::iterator sIter;
00403   EntryMap::iterator eIter;
00404 
00405   if( (sIter = m_iniData.find( _section )) == m_iniData.end() )
00406       return;
00407 
00408   if( (eIter = sIter->second.find( _key )) != sIter->second.end() )
00409       sIter->second.erase( eIter );
00410 }
00411 
00412 
00413 // -----------------------------------------------------------------------------
00414 
00415 void INIFile::delete_section( const QString & _sectionname )
00416 {
00417   m_iniData.erase( _sectionname );
00418 }
00419 
00420 
00421 // -----------------------------------------------------------------------------
00422 
00423 
00424 bool INIFile::get_entry( QString & _val,
00425                          const QString & _section,
00426                          const QString & _key ) const
00427 {
00428   SectionMap::const_iterator sIter;
00429   EntryMap::const_iterator eIter;
00430 
00431   // does the given section exist?
00432   if( (sIter = m_iniData.find( _section )) == m_iniData.end() )
00433     return false;
00434 
00435   // does the given entry exist?
00436   if( (eIter = sIter->second.find( _key )) == sIter->second.end() )
00437     return false;
00438 
00439   _val = eIter->second;
00440   return true;
00441 }
00442 
00443 
00444 // -----------------------------------------------------------------------------
00445 
00446 
00447 bool INIFile::get_entry( double & _val,
00448                          const QString & _section,
00449                          const QString & _key ) const
00450 {
00451   SectionMap::const_iterator sIter;
00452   EntryMap::const_iterator eIter;
00453 
00454   // does the given section exist?
00455   if( (sIter = m_iniData.find( _section )) == m_iniData.end() )
00456     return false;
00457 
00458   // does the given entry exist?
00459   if( (eIter = sIter->second.find( _key )) == sIter->second.end() )
00460     return false;
00461 
00462   bool ok;
00463   _val = eIter->second.toDouble(&ok);
00464   return( ok );
00465 }
00466 
00467 
00468 // -----------------------------------------------------------------------------
00469 
00470 
00471 bool INIFile::get_entry( float & _val,
00472                          const QString & _section,
00473                          const QString & _key ) const
00474 {
00475   SectionMap::const_iterator sIter;
00476   EntryMap::const_iterator eIter;
00477 
00478   // does the given section exist?
00479   if( (sIter = m_iniData.find( _section )) == m_iniData.end() )
00480     return false;
00481 
00482   // does the given entry exist?
00483   if( (eIter = sIter->second.find( _key )) == sIter->second.end() )
00484     return false;
00485 
00486   bool ok;
00487   _val = eIter->second.toFloat(&ok);
00488   return( ok );
00489 }
00490 
00491 
00492 // -----------------------------------------------------------------------------
00493 
00494 
00495 bool INIFile::get_entry( int & _val,
00496                          const QString & _section,
00497                          const QString & _key ) const
00498 {
00499   SectionMap::const_iterator sIter;
00500   EntryMap::const_iterator eIter;
00501 
00502   // does the given section exist?
00503   if( (sIter = m_iniData.find( _section )) == m_iniData.end() )
00504     return false;
00505 
00506   // does the given entry exist?
00507   if( (eIter = sIter->second.find( _key )) == sIter->second.end() )
00508     return false;
00509 
00510   bool ok;
00511   _val = eIter->second.toInt(&ok);
00512   return( ok );
00513 }
00514 
00515 
00516 // -----------------------------------------------------------------------------
00517 
00518 bool INIFile::get_entry( unsigned int & _val,
00519                          const QString & _section,
00520                          const QString & _key ) const
00521 {
00522   SectionMap::const_iterator sIter;
00523   EntryMap::const_iterator eIter;
00524 
00525   // does the given section exist?
00526   if( (sIter = m_iniData.find( _section )) == m_iniData.end() )
00527     return false;
00528 
00529   // does the given entry exist?
00530   if( (eIter = sIter->second.find( _key )) == sIter->second.end() )
00531     return false;
00532 
00533   bool ok;
00534   _val = eIter->second.toUInt(&ok);
00535   return( ok );
00536 }
00537 
00538 
00539 // -----------------------------------------------------------------------------
00540 
00541 
00542 bool INIFile::get_entry( bool & _val,
00543                          const QString & _section,
00544                          const QString & _key) const
00545 {
00546   SectionMap::const_iterator sIter;
00547   EntryMap::const_iterator eIter;
00548 
00549   // does the given section exist?
00550   if( (sIter = m_iniData.find( _section )) == m_iniData.end() )
00551     return false;
00552 
00553   // does the given entry exist?
00554   if( (eIter = sIter->second.find( _key )) == sIter->second.end() )
00555     return false;
00556 
00557   if( eIter->second == "true" || eIter->second == "false" ) {
00558     _val = (eIter->second == "true");
00559     return true;
00560   } else {
00561     return false;
00562   }
00563 }
00564 
00565 
00566 // -----------------------------------------------------------------------------
00567 
00568 
00569 bool INIFile::get_entry( std::vector<float> & _val,
00570                          const QString & _section,
00571                          const QString & _key ) const
00572 {
00573   SectionMap::const_iterator sIter;
00574   EntryMap::const_iterator eIter;
00575 
00576   _val.clear();
00577 
00578   // does the given section exist?
00579   if( (sIter = m_iniData.find( _section )) == m_iniData.end() )
00580     return false;
00581 
00582   // does the given entry exist?
00583   if( (eIter = sIter->second.find( _key )) == sIter->second.end() )
00584     return false;
00585 
00586   QStringList list = eIter->second.split(';');
00587 
00588   bool ok = true;
00589   for ( int i = 0 ; i < list.size(); ++i) {
00590     if ( list[i].isEmpty() )
00591       continue;
00592     bool tmpOk = false;
00593     _val.push_back(list[i].toFloat(&tmpOk));
00594     ok &= tmpOk;
00595   }
00596 
00597   return ok;
00598 }
00599 
00600 
00601 // -----------------------------------------------------------------------------
00602 
00603 
00604 bool INIFile::get_entry( std::vector<double> & _val,
00605                          const QString & _section,
00606                          const QString & _key ) const
00607 {
00608   SectionMap::const_iterator sIter;
00609   EntryMap::const_iterator eIter;
00610 
00611   _val.clear();
00612 
00613   // does the given section exist?
00614   if( (sIter = m_iniData.find( _section )) == m_iniData.end() )
00615     return false;
00616 
00617   // does the given entry exist?
00618   if( (eIter = sIter->second.find( _key )) == sIter->second.end() )
00619     return false;
00620 
00621   QStringList list = eIter->second.split(';');
00622 
00623   bool ok = true;
00624   for ( int i = 0 ; i < list.size(); ++i) {
00625     if ( list[i].isEmpty() )
00626       continue;
00627     bool tmpOk = false;
00628     _val.push_back(list[i].toDouble(&tmpOk));
00629     ok &= tmpOk;
00630   }
00631 
00632   return ok;
00633 }
00634 
00635 
00636 // -----------------------------------------------------------------------------
00637 
00638 
00639 bool INIFile::get_entry( std::vector<int> & _val,
00640           const QString & _section,
00641           const QString & _key ) const
00642 {
00643   SectionMap::const_iterator sIter;
00644   EntryMap::const_iterator eIter;
00645 
00646   _val.clear();
00647 
00648   // does the given section exist?
00649   if( (sIter = m_iniData.find( _section )) == m_iniData.end() )
00650     return false;
00651 
00652   // does the given entry exist?
00653   if( (eIter = sIter->second.find( _key )) == sIter->second.end() )
00654     return false;
00655 
00656   QStringList list = eIter->second.split(';');
00657 
00658   bool ok = true;
00659   for ( int i = 0 ; i < list.size(); ++i) {
00660     if ( list[i].isEmpty() )
00661       continue;
00662     bool tmpOk = false;
00663     _val.push_back(list[i].toInt(&tmpOk));
00664     ok &= tmpOk;
00665   }
00666 
00667   return ok;
00668 }
00669 
00670 
00671 bool INIFile::get_entry( std::vector<QString> & _val,
00672           const QString & _section,
00673           const QString & _key ) const
00674 {
00675   SectionMap::const_iterator sIter;
00676   EntryMap::const_iterator eIter;
00677 
00678   _val.clear();
00679 
00680   // does the given section exist?
00681   if( (sIter = m_iniData.find( _section )) == m_iniData.end() )
00682     return false;
00683 
00684   // does the given entry exist?
00685   if( (eIter = sIter->second.find( _key )) == sIter->second.end() )
00686     return false;
00687 
00688   QStringList list = eIter->second.split(';');
00689 
00690   bool ok = true;
00691   for ( int i = 0 ; i < list.size(); ++i) {
00692     if ( list[i].isEmpty() )
00693       continue;
00694     _val.push_back(list[i]);
00695   }
00696 
00697   return ok;
00698 }
00699 
00700 bool INIFile::get_entry( QStringList & _val,
00701           const QString & _section,
00702           const QString & _key ) const
00703 {
00704   SectionMap::const_iterator sIter;
00705   EntryMap::const_iterator eIter;
00706 
00707   _val.clear();
00708 
00709   // does the given section exist?
00710   if( (sIter = m_iniData.find( _section )) == m_iniData.end() )
00711     return false;
00712 
00713   // does the given entry exist?
00714   if( (eIter = sIter->second.find( _key )) == sIter->second.end() )
00715     return false;
00716 
00717   _val = eIter->second.split(';');
00718 
00719   bool ok = true;
00720   if ( _val.isEmpty() )
00721     ok = false;
00722 
00723   return ok;
00724 }

acg pic Project OpenFlipper, ©  Computer Graphics Group, RWTH Aachen. Documentation generated using doxygen .