|
STK++ 1.0
|
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