STK++ 1.0
STK_IPage.cpp
Go to the documentation of this file.
00001 /*--------------------------------------------------------------------*/
00002 /*     Copyright (C) 2004-2007  Serge Iovleff
00003 
00004     This program 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 of the
00007     License, or (at your option) any later version.
00008 
00009     This program 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 program; if not, write to the
00016     Free Software Foundation, Inc.,
00017     59 Temple Place,
00018     Suite 330,
00019     Boston, MA 02111-1307
00020     USA
00021 
00022     Contact : Serge.Iovleff@stkpp.org
00023 */
00024 
00025 /*
00026  * Project:  stkpp::DManager
00027  * created on: 22 avr. 2010
00028  * Purpose:  Public interface of the IPage class.
00029  * Author:   iovleff, serge.iovleff@stkpp.org
00030  **/
00031 
00035 // C++ headers
00036 #include <algorithm>
00037 
00038 // STK headers
00039 #include "../include/STK_IPage.h"
00040 #include "../include/STK_DManager_Util.h"
00041 
00042 #include "../../STKernel/include/STK_Exceptions.h"
00043 #include "../../STKernel/include/STK_String_Util.h"
00044 
00045 namespace STK
00046 {
00047 // remove all occurrences of the char @c c
00048 //static void removeAllChar( STK::String & str, STK::Char c )
00049 //{
00050 //  str.erase( std::remove( str.begin(), str.end(), c ), str.end() );
00051 //}
00052 
00053 // remove all occurrences after the char @c c
00054 static void removeComments( String & str, Char c )
00055 {
00056   String::size_type pos = str.find(c);
00057   if (pos < str.size())
00058   {
00059     str.resize(pos);
00060   }
00061 }
00062 
00063 // create pagename_
00064 static void createKeyWord( String & str, Integer const& level )
00065 {
00066   // remove all occurrences of CHAR_OPENBRACKET
00067   str.erase( std::remove( str.begin(), str.end(), CHAR_OPENBRACKET ), str.end() );
00068   // remove all occurrences of CHAR_CLOSEBRACKET
00069   str.erase( std::remove( str.begin(), str.end(), CHAR_CLOSEBRACKET ), str.end() );
00070   // add CHAR_OPENBRACKET and CHAR_CLOSEBRACKET
00071   str.insert(0, level, CHAR_OPENBRACKET).append(level, CHAR_CLOSEBRACKET);
00072 }
00073 
00074 
00075 /* Constructor.
00076  * @param level level of the page */
00077 IPage::IPage( String const& name, Integer const& level, bool isOptional)
00078             : isOptional_(isOptional)
00079             , name_(name)
00080             , level_(level)
00081             , keyword_(name_)
00082 {
00083   toUpperString(name_);
00084   toUpperString(keyword_);
00085   createKeyWord(keyword_, level);
00086 }
00087 
00088 /* Destructor */
00089 IPage::~IPage()
00090 { }
00091 
00092 /* Copy constructor.
00093  * @param page the page to copy
00094  **/
00095 IPage::IPage( IPage const& page)
00096 {
00097   name_ = page.name_;
00098   level_ = page.level_;
00099   isOptional_ = page.isOptional_;
00100   keyword_ = page.keyword_;
00101   options_ = page.options_;
00102 }
00103 
00107 void IPage::addPage(IPage const& page)
00108 {
00109   // look how many bracket
00110   page.level_ = level_ +1;
00111   createKeyWord(page.keyword_, page.level_);
00112   addOption(Option(page));
00113 }
00114 
00115 
00116 /* @brief read in options in a stream
00117  * @param is input stream
00118  */
00119 void IPage::read( istream& is)
00120 {
00121   // find page
00122   if (!findKeyword(is))
00123   {
00124     if ( !isOptional_ ) // throw error message if the page is not optional
00125     {
00126       msg_error_ = "Page " + std::string(_T(keyword_.c_str())) + " not found \n";
00127       throw runtime_error(msg_error_);
00128     }
00129     else return;
00130   }
00131   // get current position of the stream as we will need to pass twice
00132   istream::pos_type pos = is.tellg();
00133 
00134   // read standard options for that page until eof or a new option is discovered
00135   String  line;
00136   while (std::getline(is, line))
00137   {
00138     // remove comments
00139     removeComments(line, CHAR_COMMENT);
00140     DManager::removeCharBeforeAndAfter(line, CHAR_BLANK);
00141     DManager::removeCharBeforeAndAfter(line, CHAR_TAB);
00142     // nothing to do
00143     if (line.empty()) continue;
00144     // we encounter a page name
00145     if (line.at(0) == CHAR_OPENBRACKET) break;
00146     // ignore line if it is not an option
00147     if (line.find_first_of(CHAR_EQUAL) != line.npos)
00148     {
00149       if (!processLine(line))
00150         throw runtime_error(msg_error_);
00151     }
00152     else
00153     {
00154       msg_error_ = "ERROR. In page " + std::string(_T(name_.c_str()))
00155                  + ". Incorrect line.\n";
00156       throw runtime_error(msg_error_);
00157     }
00158   }
00159   // clear states
00160   is.clear();
00161   // read sub-option pages
00162   for( ContOption::iterator it = options_.begin(); it != options_.end(); it++)
00163   {
00164     if (it->type() == Option::page_)
00165     { // set back iostream
00166       is.seekg(pos);
00167       // and read the sub-page
00168       it->read(is);
00169     }
00170   }
00171   // validate reading
00172   validate();
00173 }
00174 
00175 /* @brief write out options in a stream
00176  *  @param os output stream
00177  */
00178 void IPage::write( ostream& os) const
00179 {
00180   // padding
00181   const Integer nbWhiteSpace = 2*(level_-1);
00182   const String padding = String((int)nbWhiteSpace, CHAR_BLANK);
00183   // write keyword
00184   os << padding << keyword_ << STRING_NL;
00185   // write options
00186   for( ContOption::const_iterator it = options_.begin(); it != options_.end(); it++)
00187   {
00188     os << padding; it->write(os);
00189     if (it->type() != Option::page_) os << STRING_NL;
00190   }
00191   os.flush();
00192 }
00193 
00194 /*  internal bookkeeping.
00195  *  @param name name of the Page to find
00196  *  @return NULL if the variable is not found, the page otherwise
00197  **/
00198 Option const& IPage::option( String const& name) const
00199 {
00200   String Uname = toUpperString(name);
00201   // read all pages
00202   for (ContOption::const_iterator it = options_.begin(); it != options_.end(); it++)
00203   {
00204     // read curent page
00205     if (it->name() == Uname) return *it;
00206   }
00207   msg_error_ = _T("In Ipage::Option(");
00208   msg_error_ += name;
00209   msg_error_ +=_T(") const; Option not found\n");
00210   throw runtime_error(msg_error_);
00211 }
00212 
00213 /*  internal bookkeeping.
00214  *  @param name name of the Page to find
00215  *  @return NULL if the variable is not found, the page otherwise
00216  **/
00217 Option& IPage::option( String const& name)
00218 {
00219   String Uname = toUpperString(name);
00220   // read all pages
00221   for (ContOption::iterator it = options_.begin(); it != options_.end(); it++)
00222   {
00223     // read curent page
00224     if (it->name() == Uname) return *it;
00225   }
00226   msg_error_ = _T("In IPage::option(");
00227   msg_error_ += name;
00228   msg_error_ +=_T("); Option not found\n");
00229   throw runtime_error(msg_error_);
00230 }
00231 
00232 
00233 
00234 bool IPage::findKeyword( istream& is) const
00235 {
00236   // Reading lines
00237   String  line;
00238   // search page
00239   while (std::getline(is, line))
00240   {
00241     // remove comments and space characters before and after
00242     removeComments(line, CHAR_COMMENT);
00243     DManager::removeCharBeforeAndAfter(line, CHAR_BLANK);
00244     DManager::removeCharBeforeAndAfter(line, CHAR_TAB);
00245     toUpperString(line);
00246     // check if the the keyword_ is encountered
00247     if (line == keyword_) return true ;
00248   }
00249   // the keyword_ have not been found
00250   return false;
00251 }
00252 
00253 /*  process the input line in order to obtain a .
00254  *  @param is input stringstream to process
00255  *  @return @c true if the keyword have been found, @c false otherwise
00256  */
00257 bool IPage::processLine( String const& line)
00258 {
00259   String::size_type pos = line.find_first_of(CHAR_EQUAL);
00260   // get the option name before '='
00261   String optName = line.substr(0,pos);
00262   DManager::removeCharBeforeAndAfter(optName, CHAR_BLANK);
00263   DManager::removeCharBeforeAndAfter(optName, CHAR_TAB);
00264   toUpperString(optName);
00265   // get the option value after character '='
00266   String optValue = line.substr(pos+1);
00267   DManager::removeCharBeforeAndAfter(optValue, CHAR_BLANK);
00268   DManager::removeCharBeforeAndAfter(optValue, CHAR_TAB);
00269   // iterate among all the options and find the option
00270   for( ContOption::iterator it = options_.begin(); it != options_.end(); it++)
00271   {
00272     // compare the name of the option with those into the page
00273     if (it->name().compare(optName) == 0)
00274     {
00275       it->setValue(optValue);
00276       return true;
00277     }
00278   }
00279   // the option name is not in the page
00280   msg_error_ = "ERROR. In " + name_ + ", option: " + optName
00281              + " is unknown.\n";
00282   return false;
00283 }
00284 
00285 
00286 } // namespace STK
00287