libFAUDES
Sections
Index
|
cfl_tokenreader.cppGo to the documentation of this file.00001 /** @file cfl_tokenreader.cpp @brief Class TokenReader */ 00002 00003 /* FAU Discrete Event Systems Library (libfaudes) 00004 00005 Copyright (C) 2006 Bernd Opitz 00006 Copyright (C) 2006 Thomas Moor 00007 Exclusive copyright is granted to Klaus Schmidt 00008 00009 This library is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU Lesser General Public 00011 License as published by the Free Software Foundation; either 00012 version 2.1 of the License, or (at your option) any later version. 00013 00014 This library is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public 00020 License along with this library; if not, write to the Free Software 00021 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 00022 00023 00024 00025 00026 #include "cfl_tokenwriter.h" 00027 #include "cfl_tokenreader.h" 00028 00029 namespace faudes { 00030 00031 // TokenReader(mode,instring) 00032 TokenReader::TokenReader(Mode mode, const std::string& rInString) 00033 : mMode(mode), mpStream(NULL), mFileName("") 00034 { 00035 switch(mode) { 00036 case String: 00037 // use mSStream 00038 FD_DV("TokenReader::Tokenreader(String, ...): " << rInString); 00039 mpSStream= new std::istringstream(rInString, std::istringstream::in | std::istringstream::binary); 00040 mpStream= mpSStream; 00041 Rewind(); 00042 break; 00043 case File: 00044 // set up mFStream 00045 FD_DV("TokenReader::Tokenreader(File, \"" << rInString <<"\")"); 00046 mFStream.exceptions(std::ios::badbit|std::ios::failbit); 00047 try{ 00048 mFStream.open(rInString.c_str(), std::ios::in | std::ios::binary); 00049 } 00050 catch (std::ios::failure&) { 00051 std::stringstream errstr; 00052 errstr << "Exception opening/reading file \""<< rInString << "\""; 00053 throw Exception("TokenReader::TokenReader", errstr.str(), 1); 00054 } 00055 mFileName=rInString; 00056 mpStream=&mFStream; 00057 Rewind(); 00058 break; 00059 default: 00060 std::stringstream errstr; 00061 errstr << "Invalid Mode / Not implemented"; 00062 throw Exception("TokenReader::TokenReader(mode,instring)", errstr.str(), 1); 00063 } 00064 } 00065 00066 00067 // TokenReader(rFilename) 00068 TokenReader::TokenReader(const std::string& rFilename) 00069 : mMode(File), mpStream(NULL), mFileName(rFilename) 00070 { 00071 // set up mFStream 00072 FD_DV("TokenReader::Tokenreader(File, \"" << rFilename <<"\")"); 00073 mFStream.exceptions(std::ios::badbit|std::ios::failbit); 00074 try{ 00075 mFStream.open(rFilename.c_str(), std::ios::in | std::ios::binary); 00076 } 00077 catch (std::ios::failure&) { 00078 std::stringstream errstr; 00079 errstr << "Exception opening/reading file \""<< rFilename << "\""; 00080 throw Exception("TokenReader::TokenReader", errstr.str(), 1); 00081 } 00082 mFileName=rFilename; 00083 mpStream=&mFStream; 00084 Rewind(); 00085 } 00086 00087 00088 // destruct 00089 TokenReader::~TokenReader(void) { 00090 if(mMode==String) delete mpSStream; 00091 } 00092 00093 // Stream() 00094 std::istream* TokenReader::Streamp(void) { 00095 return mpStream; 00096 } 00097 00098 // Rewind() 00099 void TokenReader::Rewind(void) { 00100 FD_DV("TokenReader::Rewind: \"" << mFileName <<"\""); 00101 try { 00102 mpStream->clear(); 00103 mpStream->seekg(0); 00104 mPeekToken.SetNone(); 00105 mLevel=0; 00106 mLevelLabel.clear(); 00107 mLevelLabel.push_back("STREAM"); 00108 mLevelPos.clear(); 00109 mLevelPos.push_back(0); 00110 mLevelLine.clear(); 00111 mLevelLine.push_back(1); 00112 mSeekLevel.clear(); 00113 mLineCount=1; 00114 mFilePos=0; 00115 } 00116 catch (std::ios::failure&) { 00117 std::stringstream errstr; 00118 errstr << "Exception opening/reading file in "<< FileLine(); 00119 throw Exception("TokenReader::Rewind", errstr.str(), 1); 00120 } 00121 } 00122 00123 00124 // FileName() 00125 std::string TokenReader::FileName(void) const { 00126 return mFileName; 00127 } 00128 00129 // Peek(token) 00130 bool TokenReader::Peek(Token& token) { 00131 // read to peek buffer 00132 if(mPeekToken.IsNone()) { 00133 try{ 00134 mLineCount += mPeekToken.Read(mpStream); 00135 } catch (std::ios::failure&) { 00136 std::stringstream errstr; 00137 errstr << "Exception opening/reading file in "<< FileLine(); 00138 throw Exception("TokenReader::Peek", errstr.str(), 1); 00139 } 00140 } 00141 // get from peek buffer 00142 token=mPeekToken; 00143 // substitute empty sections 00144 if(token.IsEmpty()) token.ClrEnd(); 00145 // done 00146 FD_DV("TokenReader: Peek: " << token.Str()); 00147 return !token.IsNone(); 00148 } 00149 00150 // Get(token) 00151 bool TokenReader::Get(Token& token) { 00152 bool res; 00153 // get token from peek buffer 00154 res=Peek(token); 00155 // invalidate buffer: case a 00156 if(!mPeekToken.IsEmpty()) mPeekToken.SetNone(); 00157 // invalidate buffer: case b 00158 if(mPeekToken.IsEmpty()) { 00159 FD_DV("TokenReader: fake from : " << mPeekToken.Str()); 00160 mPeekToken.SetEnd(std::string(mPeekToken.StringValue())); 00161 } 00162 // bail out n error 00163 if(!res) return false; 00164 // track state (level of nested sections, filepos etc) 00165 if(!token.IsBegin("br") && !token.IsEnd("br")) { 00166 mFilePos=mpStream->tellg(); 00167 if(token.IsBegin()) { 00168 mLevel++; 00169 mLevelLabel.push_back(token.StringValue()); 00170 mLevelPos.push_back(mFilePos); 00171 mLevelLine.push_back(mLineCount); 00172 } 00173 if(token.IsEnd()) { 00174 mLevel--; 00175 if(mLevelLabel.size()<=0 || mLevelPos.size()<=0 || mLevelLine.size()<=0) { 00176 #ifdef FAUDES_CHECKED 00177 FD_WARN("TokenReader::Get(): Unbalanced end of section \"" << token.StringValue() << "\" at " << FileLine()); 00178 #endif 00179 token.SetNone(); 00180 return false; 00181 } 00182 #ifdef FAUDES_CHECKED 00183 if(token.StringValue()!=mLevelLabel.back()) 00184 FD_WARN("TokenReader::Get(): end of section \"" << token.StringValue() << "\" at " << FileLine() << " should match \"" << mLevelLabel.back() << "\" at line " << mLevelLine.back() ); 00185 #endif 00186 mLevelLabel.pop_back(); 00187 mLevelPos.pop_back(); 00188 mLevelLine.pop_back(); 00189 } 00190 } 00191 FD_DV("TokenReader:Get(): " << token.Str()); 00192 00193 return res; 00194 } 00195 00196 // SeekBegin(label) 00197 void TokenReader::SeekBegin(const std::string& rLabel) { 00198 Token token; 00199 SeekBegin(rLabel,token); 00200 } 00201 00202 // SeekBegin(label) 00203 void TokenReader::SeekBegin(const std::string& rLabel, Token& rToken) { 00204 // search for begin at any descending level, no rewind 00205 FD_DV("TokenReader::SeekBegin: " << rLabel << " at " << FileLine() << " level " << mLevel); 00206 int level=mLevel; 00207 long int startpos=mFilePos; 00208 int startline=mLineCount; 00209 for (;;) { 00210 // exception: did not get a token at all (incl. eof) 00211 if(!Peek(rToken)) { 00212 Rewind(); 00213 std::stringstream errstr; 00214 errstr << "Section \"" << rLabel << "\" expected at " << FileLine() << " no more tokens"; 00215 throw Exception("TokenReader::SeekBegin", errstr.str(), 51); 00216 } 00217 // exception: current section ends 00218 if((rToken.Type() == Token::End) && (mLevel == level)) { 00219 mpStream->seekg(startpos); 00220 mLineCount=startline; 00221 mPeekToken.SetNone(); 00222 std::stringstream errstr; 00223 errstr << "Section \"" << rLabel << "\" expected at " << FileLine() 00224 << "current section ended unexpected. Found: " << rToken.StringValue() << " Type " << rToken.Type(); 00225 throw Exception("TokenReader::SeekBegin", errstr.str(), 51); 00226 } 00227 // success: found begin section 00228 if ((rToken.IsBegin()) && (rToken.StringValue() == rLabel)) 00229 break; 00230 // go on seeking 00231 Get(rToken); 00232 } 00233 } 00234 00235 // ReadBegin(label) 00236 void TokenReader::ReadBegin(const std::string& rLabel) { 00237 Token token; 00238 ReadBegin(rLabel,token); 00239 } 00240 00241 // ReadBegin(label,token) 00242 void TokenReader::ReadBegin(const std::string& rLabel, Token& rToken) { 00243 FD_DV("Looking for Section \"" << rLabel << "\""); 00244 try { 00245 int level=mLevel; 00246 bool firstgo=true; 00247 long int startpos=mFilePos; 00248 FD_DV("section level " << level << " current pos " << startpos << " begin of section " << mLevelPos[level]); 00249 // search for begin at current level 00250 for (;;) { 00251 // exception: did not get a token at all (incl eof) 00252 if(!Peek(rToken)) { 00253 std::stringstream errstr; 00254 errstr << "Section \"" << rLabel << "\" expected at " << FileLine() << ", no token at all"; 00255 throw Exception("TokenReader::ReadBegin Peek", errstr.str(), 51); 00256 } 00257 // success: found begin section 00258 if((rToken.IsBegin()) && (rToken.StringValue() == rLabel) && (mLevel==level)) { 00259 Get(rToken); 00260 break; 00261 } 00262 // rewind once when current section ends 00263 if(rToken.IsEnd() && !rToken.IsBegin() && (mLevel == level) && firstgo) { 00264 mpStream->seekg(mLevelPos[level]); 00265 mFilePos=mLevelPos[level]; 00266 mLineCount=mLevelLine[level]; 00267 firstgo=false; 00268 mPeekToken.SetNone(); 00269 continue; 00270 } 00271 // exception: did not find begin label 00272 if((mFilePos>=startpos) && (!firstgo)) { 00273 std::stringstream errstr; 00274 errstr << "Section \"" << rLabel << "\" expected at " << FileLine() << ", did not find begin label"; 00275 throw Exception("TokenReader::ReadBegin Missed", errstr.str(), 51); 00276 } 00277 // skip this token 00278 Get(rToken); 00279 } 00280 } 00281 // catch my seek/tell errors 00282 catch (std::ios::failure&) { 00283 std::stringstream errstr; 00284 errstr << "Section \"" << rLabel << "\" expected at " << FileLine(); 00285 throw Exception("TokenReader::ReadBegin Rewind", errstr.str(), 1); 00286 } 00287 } 00288 00289 00290 // ExistsBegin(label) 00291 bool TokenReader::ExistsBegin(const std::string& rLabel) { 00292 FD_DV("TokenReader::ExistsBegin(): looking for Section \"" << rLabel << "\""); 00293 try { 00294 int level=mLevel; 00295 bool firstgo=true; 00296 long int startpos=mFilePos; 00297 FD_DV("section level " << level << " current pos " << startpos << " begin of section " << mLevelPos[level]); 00298 Token token; 00299 // search for begin at current level 00300 for(;;) { 00301 // fail: did not get a token at all (incl eof) 00302 if(!Peek(token)) { 00303 return false; 00304 } 00305 // success: found begin section 00306 if((token.IsBegin()) && (token.StringValue() == rLabel) && (mLevel==level)) { 00307 return true; 00308 } 00309 // rewind once when current section ends 00310 if((token.IsEnd() && !token.IsBegin()) && (mLevel == level) && firstgo) { 00311 mpStream->seekg(mLevelPos[level]); 00312 mFilePos=mLevelPos[level]; 00313 mLineCount=mLevelLine[level]; 00314 firstgo=false; 00315 mPeekToken.SetNone(); 00316 continue; 00317 } 00318 // fail: did not find begin label 00319 if((mFilePos>=startpos) && (!firstgo)) { 00320 return false; 00321 } 00322 // skip this token 00323 Get(token); 00324 } 00325 } 00326 // catch my seek/tell errors 00327 catch (std::ios::failure&) { 00328 std::stringstream errstr; 00329 errstr << "Section \"" << rLabel << "\" expected at " << FileLine(); 00330 throw Exception("TokenReader::ReadBegin Rewind", errstr.str(), 1); 00331 } 00332 return false; 00333 } 00334 00335 // ReadEnd(label) 00336 void TokenReader::ReadEnd(const std::string& rLabel) { 00337 FD_DV("TokenReader::ReadEnd: " << rLabel << " at " << FileLine() ); 00338 // search for end at current level 00339 int level=mLevel; 00340 Token token; 00341 for (;;) { 00342 // exception: did not get a token at all 00343 if(!Peek(token)) { 00344 std::stringstream errstr; 00345 errstr << "end of Section \"" << rLabel << "\" expected at " << FileLine(); 00346 throw Exception("TokenReader::ReadEnd", errstr.str(), 51); 00347 } 00348 // success: found end of current section 00349 if(token.IsEnd() && !token.IsBegin() && (token.StringValue() == rLabel) && (mLevel==level)) { 00350 Get(token); 00351 break; 00352 } 00353 // exception: current section ends with unexpected label 00354 if(mLevel<level) { 00355 std::stringstream errstr; 00356 errstr << "end of Section \"" << rLabel << "\" expected at " << FileLine(); 00357 throw Exception("TokenReader::ReadEnd", errstr.str(), 51); 00358 } 00359 // get the token and continue 00360 Get(token); 00361 } 00362 } 00363 00364 // Recover() 00365 bool TokenReader::Recover(int level) { 00366 // trivial cases 00367 if(level>mLevel) return false; 00368 if(level==mLevel) return true; 00369 // loop until match 00370 Token token; 00371 while(Get(token)) 00372 if(mLevel<=level) break; 00373 // done 00374 return level==mLevel; 00375 } 00376 00377 // Eos(label) 00378 bool TokenReader::Eos(const std::string& rLabel) { 00379 // peek token and check for end of section 00380 Token token; 00381 Peek(token); 00382 if(! (token.IsEnd() && !token.IsBegin())) 00383 return false; 00384 if((token.IsEnd() && !token.IsBegin()) && (token.StringValue() == rLabel)) 00385 return true; 00386 std::stringstream errstr; 00387 errstr << "Section End\"" << rLabel << "\" expected at " << FileLine(); 00388 throw Exception("TokenReader::Eos", errstr.str(), 51); 00389 return false; 00390 } 00391 00392 00393 // ReadInteger() 00394 long int TokenReader::ReadInteger(void) { 00395 Token token; 00396 Get(token); 00397 if(!token.IsInteger()) { 00398 std::stringstream errstr; 00399 errstr << "Integer expected at " << FileLine(); 00400 throw Exception("TokenReader::TokenReader", errstr.str(), 50); 00401 } 00402 return token.IntegerValue(); 00403 } 00404 00405 // ReadFloat() 00406 double TokenReader::ReadFloat(void) { 00407 Token token; 00408 Get(token); 00409 if((!token.IsFloat()) && (!token.IsInteger())) { 00410 std::stringstream errstr; 00411 errstr << "Float expected at " << FileLine(); 00412 throw Exception("TokenReader::TokenReader", errstr.str(), 50); 00413 } 00414 return token.FloatValue(); 00415 } 00416 00417 // ReadString() 00418 const std::string& TokenReader::ReadString(void) { 00419 Token token; 00420 Get(token); 00421 if(!token.IsString()) { 00422 std::stringstream errstr; 00423 errstr << "Name expected at " << FileLine(); 00424 throw Exception("TokenReader::TokenReader", errstr.str(), 50); 00425 } 00426 mLastString=token.StringValue(); 00427 return(mLastString); 00428 } 00429 00430 00431 // ReadOption() 00432 const std::string& TokenReader::ReadOption(void) { 00433 Token token; 00434 Get(token); 00435 if(!token.IsOption()) { 00436 std::stringstream errstr; 00437 errstr << "Option expected at " << FileLine(); 00438 throw Exception("TokenReader::TokenReader", errstr.str(), 50); 00439 } 00440 mLastString=token.OptionValue(); 00441 return(mLastString); 00442 } 00443 00444 // ReadBinary() 00445 const std::string& TokenReader::ReadBinary(void) { 00446 Token token; 00447 Get(token); 00448 if(!token.IsBinary()) { 00449 std::stringstream errstr; 00450 errstr << "Binary string expected at " << FileLine(); 00451 throw Exception("TokenReader::TokenReader", errstr.str(), 50); 00452 } 00453 mLastString=token.StringValue(); 00454 return(mLastString); 00455 } 00456 00457 00458 // ReadText() 00459 const std::string& TokenReader::ReadText(void) { 00460 // if we have a markup token we refuse to read text 00461 if(mPeekToken.IsBegin() || mPeekToken.IsEnd()) { 00462 FD_DV("TokenReader::ReadText(): tag in buffer"); 00463 mLastString=""; 00464 return mLastString; 00465 } 00466 // do my own reading 00467 int ll=Token::ReadEscapedString(mpStream,'<',mLastString); 00468 if(ll<0) { 00469 std::stringstream errstr; 00470 errstr << "Text expected at " << FileLine(); 00471 throw Exception("TokenReader::TokenReader", errstr.str(), 50); 00472 } 00473 mLineCount+=ll; 00474 // prepend peek buffers string value (better: need rewind!) 00475 if(mPeekToken.IsString()) 00476 mLastString=mPeekToken.StringValue() + " " + mLastString; 00477 // strip leading/tailing spaces 00478 static const std::string white=" \n\t\r\v\f"; 00479 std::size_t pos1=mLastString.find_first_not_of(white); 00480 if(pos1!=std::string::npos) 00481 mLastString=mLastString.substr(pos1); 00482 else 00483 mLastString.clear(); 00484 std::size_t pos2=mLastString.find_last_not_of(white); 00485 if(pos2!=std::string::npos) 00486 mLastString.erase(pos2+1); 00487 // clear peak buffer 00488 mPeekToken.SetNone(); 00489 return mLastString; 00490 } 00491 00492 // ReadCharacterData() 00493 const std::string& TokenReader::ReadCharacterData(void) { 00494 // if we have a markup token we refuse to read character data 00495 if(mPeekToken.IsBegin() || mPeekToken.IsEnd()) { 00496 FD_DV("TokenReader::ReadCharacterData(): tag in buffer"); 00497 mLastString=""; 00498 return mLastString; 00499 } 00500 // do my own reading 00501 int ll=Token::ReadCharacterData(mpStream,mLastString); 00502 if(ll<0) { 00503 std::stringstream errstr; 00504 errstr << "Text expected at " << FileLine(); 00505 throw Exception("TokenReader::TokenReader", errstr.str(), 50); 00506 } 00507 mLineCount+=ll; 00508 // prepend peek buffers string value (better: need rewind!) 00509 if(mPeekToken.IsString()) 00510 mLastString=mPeekToken.StringValue() + " " + mLastString; 00511 // invalidate buffer 00512 mPeekToken.SetNone(); 00513 return mLastString; 00514 } 00515 00516 // ReadSection() 00517 const std::string& TokenReader::ReadSection(void) { 00518 // record current level 00519 int clevel = Level(); 00520 // setup token writer for destination 00521 TokenWriter tw(TokenWriter::String); 00522 // token copy loop 00523 while(true) { 00524 // see whether we can grab and copy some character data 00525 std::string cdata=ReadCharacterData(); 00526 tw.WriteCharacterData(cdata); 00527 // break end of my level 00528 Token token; 00529 if(!Peek(token)) break; 00530 if(token.IsEnd() && !token.IsBegin() && Level()==clevel) 00531 break; 00532 // get and copy markup token 00533 Get(token); 00534 tw.Write(token); 00535 } 00536 // done 00537 mLastString=tw.Str(); 00538 return mLastString; 00539 } 00540 00541 00542 // Line() 00543 int TokenReader::Line(void) const { 00544 return mLineCount; 00545 } 00546 00547 // FileLine() 00548 std::string TokenReader::FileLine(void) const { 00549 if(mFileName!="") 00550 return "("+ mFileName + ":" + ToStringInteger(mLineCount) +")"; 00551 else 00552 return "(#" + ToStringInteger(mLineCount) +")"; 00553 } 00554 00555 } // namespace faudes |
libFAUDES 2.22k --- 2013.04.02 --- c++ source docu by doxygen