libFAUDES

Sections

Index

cfl_tokenreader.cpp

Go 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_tokenreader.h"
00027 
00028 namespace faudes {
00029 
00030 // TokenReader(mode,instring)
00031 TokenReader::TokenReader(Mode mode, const std::string& rInString)
00032   : mMode(mode), mpStream(NULL), mFileName("") 
00033 {
00034   switch(mode) {
00035   case String: 
00036     // use mSStream
00037     FD_DV("TokenReader::Tokenreader(String, ...): " << rInString);
00038     mpSStream= new std::istringstream(rInString, std::istringstream::in | std::istringstream::binary);
00039     mpStream= mpSStream;
00040     Rewind();
00041     break;
00042   case File: 
00043     // set up mFStream
00044     FD_DV("TokenReader::Tokenreader(File, \"" << rInString <<"\")");
00045     mFStream.exceptions(std::ios::badbit|std::ios::failbit);
00046     try{
00047       mFStream.open(rInString.c_str(), std::ios::in | std::ios::binary); 
00048     } 
00049     catch (std::ios::failure&) {
00050       std::stringstream errstr;
00051       errstr << "Exception opening/reading file \""<< rInString << "\"";
00052       throw Exception("TokenReader::TokenReader", errstr.str(), 1);
00053     }
00054     mFileName=rInString;
00055     mpStream=&mFStream;
00056     Rewind();
00057     break;
00058   default:
00059     std::stringstream errstr;
00060     errstr << "Invalid Mode / Not implemented";
00061     throw Exception("TokenReader::TokenReader(mode,instring)", errstr.str(), 1);
00062   }
00063 }
00064 
00065 
00066 // TokenReader(rFilename)
00067 TokenReader::TokenReader(const std::string& rFilename) 
00068   : mMode(File), mpStream(NULL), mFileName(rFilename) 
00069 {
00070   // set up mFStream
00071   FD_DV("TokenReader::Tokenreader(File, \"" << rFilename <<"\")");
00072   mFStream.exceptions(std::ios::badbit|std::ios::failbit);
00073   try{
00074     mFStream.open(rFilename.c_str(), std::ios::in | std::ios::binary); 
00075   } 
00076   catch (std::ios::failure&) {
00077     std::stringstream errstr;
00078     errstr << "Exception opening/reading file \""<< rFilename << "\"";
00079     throw Exception("TokenReader::TokenReader", errstr.str(), 1);
00080   }
00081   mFileName=rFilename;
00082   mpStream=&mFStream;
00083   Rewind();
00084 }
00085 
00086 
00087 //  destruct
00088 TokenReader::~TokenReader(void) {
00089   if(mMode==String) delete mpSStream;
00090 }
00091 
00092 // Rewind()
00093 void TokenReader::Rewind(void) {
00094   FD_DV("TokenReader::Rewind: \"" << mFileName <<"\"");
00095   try {
00096     mpStream->clear();
00097     mpStream->seekg(0);
00098     mHasPeekToken=false;
00099     mPeekToken.SetNone();
00100     mLevel=0;
00101     mLevelPos.clear();
00102     mLevelPos.push_back(0);
00103     mLevelLine.clear();
00104     mLevelLine.push_back(1);
00105     mSeekLevel.clear();
00106     mLineCount=1;
00107     mFilePos=0;
00108   }
00109   catch (std::ios::failure&) {
00110     std::stringstream errstr;
00111     errstr << "Exception opening/reading file in "<< FileLine();
00112     throw Exception("TokenReader::Rewind", errstr.str(), 1);
00113   }
00114 }
00115 
00116 
00117 // FileName()
00118 std::string TokenReader::FileName(void) const {
00119   return mFileName;
00120 }
00121 
00122 // Peek(token)
00123 bool TokenReader::Peek(Token& token) {
00124   // fake end token for empty section
00125   if(!mHasPeekToken && mPeekToken.IsBegin() && mPeekToken.IsEnd()) {
00126     FD_DV("TokenReader: fake from : " << mPeekToken.Str());
00127     mPeekToken.SetEnd(std::string(mPeekToken.StringValue()));
00128     mHasPeekToken=true;
00129   }
00130   // get from peek buffer
00131   if(mHasPeekToken) { 
00132     token=mPeekToken;
00133     FD_DV("TokenReader: Peek: " << token.Str());
00134     return true;
00135   }
00136   // get new token
00137   try{
00138     mLineCount += token.Read(mpStream);
00139   } 
00140   catch (std::ios::failure&) {
00141     std::stringstream errstr;
00142     errstr << "Exception opening/reading file in "<< FileLine();
00143     throw Exception("TokenReader::Peek", errstr.str(), 1);
00144   }
00145   mPeekToken=token;
00146   FD_DV("TokenReader: Peek: " << token.Str());
00147   if(mPeekToken.IsNone()) {
00148     return false;
00149   } 
00150   mHasPeekToken=true;
00151   return true;
00152 }
00153 
00154 // Get(token)
00155 bool TokenReader::Get(Token& token) {
00156   bool res;
00157   // get token from peek buffer and invalidate
00158   res=Peek(token);
00159   mHasPeekToken=false;
00160   // track state (level of nested sections, filepos etc)
00161   if(res) {
00162     mFilePos=mpStream->tellg();
00163     if(token.IsBegin()) {
00164       mLevel++;
00165       mLevelPos.push_back(mFilePos);
00166       mLevelLine.push_back(mLineCount);
00167     }
00168     if(token.IsEnd() && !token.IsBegin()) {
00169       mLevel--;
00170       if(mLevelPos.size()<=0 || mLevelLine.size()<=0) {
00171 #ifdef FAUDES_CHECKED
00172         FD_WARN("TokenReader::Get(): Unbalanced end of section at " << FileLine());
00173 #endif
00174   token.SetNone();
00175   return false;
00176       }
00177       mLevelPos.pop_back();
00178       mLevelLine.pop_back();
00179     }
00180   }
00181   FD_DV("TokenReader:Get(): " << token.Str());
00182   return res;
00183 }
00184 
00185 // SeekBegin(label)
00186 void TokenReader::SeekBegin(const std::string& rLabel) {
00187   Token token;
00188   SeekBegin(rLabel,token);
00189 }
00190 
00191 // SeekBegin(label)
00192 void TokenReader::SeekBegin(const std::string& rLabel,  Token& rToken) {
00193   // search for begin at any descending level, no rewind
00194   FD_DV("TokenReader::SeekBegin: " << rLabel << " at " << FileLine() << " level " << mLevel);
00195   int level=mLevel;
00196   long int startpos=mFilePos;
00197   int startline=mLineCount;
00198   for (;;) {
00199     // exception: did not get a token at all (incl. eof)
00200     if(!Peek(rToken)) {
00201       Rewind();
00202       std::stringstream errstr;
00203       errstr << "Section \"" << rLabel << "\" expected at " << FileLine() << " no more tokens";
00204       throw Exception("TokenReader::SeekBegin", errstr.str(), 51);
00205     }
00206     // exception: current section ends
00207     if((rToken.Type() == Token::End) && (mLevel == level)) {
00208       mpStream->seekg(startpos);
00209       mLineCount=startline;
00210       mHasPeekToken=false;
00211       mPeekToken.SetNone();
00212       std::stringstream errstr;
00213       errstr << "Section \"" << rLabel << "\" expected at " << FileLine() 
00214        << "current section ended unexpected. Found: " << rToken.StringValue() << " Type " << rToken.Type();
00215       throw Exception("TokenReader::SeekBegin", errstr.str(), 51);
00216     }
00217     // success: found begin section
00218     if ((rToken.IsBegin()) && (rToken.StringValue() == rLabel))
00219       break;
00220     // go on seeking
00221     Get(rToken);
00222   }
00223 }
00224  
00225 // ReadBegin(label)
00226 void TokenReader::ReadBegin(const std::string& rLabel) {
00227   Token token;
00228   ReadBegin(rLabel,token);
00229 }
00230 
00231 // ReadBegin(label,token)
00232 void TokenReader::ReadBegin(const std::string& rLabel, Token& rToken) {
00233   FD_DV("Looking for Section \"" << rLabel << "\"");
00234   try {
00235     int level=mLevel;
00236     bool firstgo=true;
00237     long int startpos=mFilePos;
00238     FD_DV("section level " << level << " current pos " << startpos << " begin of section " << mLevelPos[level]);
00239     // search for begin at current level
00240     for (;;) {
00241       // exception: did not get a token at all (incl eof)
00242       if(!Peek(rToken)) {
00243   std::stringstream errstr;
00244   errstr << "Section \"" << rLabel << "\" expected at " << FileLine() << ", no token at all";
00245   throw Exception("TokenReader::ReadBegin Peek", errstr.str(), 51);
00246       }
00247       // success: found begin section
00248       if((rToken.IsBegin()) && (rToken.StringValue() == rLabel) && (mLevel==level)) {
00249   Get(rToken);
00250   break;
00251       }
00252       // rewind once when current section ends
00253       if(rToken.IsEnd() && !rToken.IsBegin() && (mLevel == level) && firstgo) {
00254   mpStream->seekg(mLevelPos[level]);
00255         mFilePos=mLevelPos[level];
00256   mLineCount=mLevelLine[level];                       
00257   firstgo=false;
00258   mHasPeekToken=false;
00259         mPeekToken.SetNone();
00260   continue;
00261       }
00262       // exception: did not find begin label
00263       if((mFilePos>=startpos) && (!firstgo)) {
00264   std::stringstream errstr;
00265   errstr << "Section \"" << rLabel << "\" expected at " << FileLine() << ", did not find begin label";
00266   throw Exception("TokenReader::ReadBegin Missed", errstr.str(), 51);
00267       }
00268       // skip this token
00269       Get(rToken);
00270     }
00271   }
00272   // catch my seek/tell errors
00273   catch (std::ios::failure&) {
00274     std::stringstream errstr;
00275     errstr << "Section \"" << rLabel << "\" expected at " << FileLine();
00276     throw Exception("TokenReader::ReadBegin Rewind", errstr.str(), 1);
00277   }
00278 }
00279  
00280 
00281 // ExistsBegin(label)
00282 bool TokenReader::ExistsBegin(const std::string& rLabel) {
00283   FD_DV("TokenReader::ExistsBegin(): looking for Section \"" << rLabel << "\"");
00284   try {
00285     int level=mLevel;
00286     bool firstgo=true;
00287     long int startpos=mFilePos;
00288     FD_DV("section level " << level << " current pos " << startpos << " begin of section " << mLevelPos[level]);
00289     Token token;
00290     // search for begin at current level
00291     for(;;) {
00292       // fail: did not get a token at all (incl eof)
00293       if(!Peek(token)) {
00294         return false;
00295       }
00296       // success: found begin section
00297       if((token.IsBegin()) && (token.StringValue() == rLabel) && (mLevel==level)) {
00298   return true;
00299       }
00300       // rewind once when current section ends
00301       if((token.IsEnd() && !token.IsBegin()) && (mLevel == level) && firstgo) {
00302   mpStream->seekg(mLevelPos[level]);
00303         mFilePos=mLevelPos[level];
00304   mLineCount=mLevelLine[level];                       
00305   firstgo=false;
00306   mHasPeekToken=false;
00307         mPeekToken.SetNone();
00308   continue;
00309       }
00310       // fail: did not find begin label
00311       if((mFilePos>=startpos) && (!firstgo)) {
00312         return false;
00313       }
00314       // skip this token
00315       Get(token);
00316     }
00317   }
00318   // catch my seek/tell errors
00319   catch (std::ios::failure&) {
00320     std::stringstream errstr;
00321     errstr << "Section \"" << rLabel << "\" expected at " << FileLine();
00322     throw Exception("TokenReader::ReadBegin Rewind", errstr.str(), 1);
00323   }
00324   return false;
00325 }
00326  
00327 // ReadEnd(label)
00328 void TokenReader::ReadEnd(const std::string& rLabel) {
00329   FD_DV("TokenReader::ReadEnd: " << rLabel << " at " << FileLine() );
00330   // search for end at current level
00331   int level=mLevel;
00332   Token token;
00333   for (;;) {
00334     // exception: did not get a token at all
00335     if(!Get(token)) {
00336       std::stringstream errstr;
00337       errstr << "end of Section \"" << rLabel << "\" expected at " << FileLine();
00338       throw Exception("TokenReader::ReadEnd", errstr.str(), 51);
00339     }
00340     // success: found end of current section
00341     if(token.IsEnd() && !token.IsBegin() && (token.StringValue() == rLabel) && (mLevel==level-1)) {
00342       break;
00343     }
00344     // exception: current section ends with unexpected label
00345     if(mLevel<level) {
00346       std::stringstream errstr;
00347       errstr << "end of Section \"" << rLabel << "\" expected at " << FileLine();
00348       throw Exception("TokenReader::ReadEnd", errstr.str(), 51);
00349     }
00350   }
00351 }
00352 
00353 // Recover()
00354 bool TokenReader::Recover(int level) {
00355   // trivial cases
00356   if(level>mLevel) return false;
00357   if(level==mLevel) return true;
00358   // loop until match
00359   Token token;
00360   while(Get(token)) 
00361     if(mLevel<=level) break;
00362   // done
00363   return level==mLevel;
00364 }
00365 
00366 // Eos(label)
00367 bool TokenReader::Eos(const std::string& rLabel) {
00368   // peek token and check for end of section
00369   Token token;
00370   Peek(token);
00371   if(! (token.IsEnd() && !token.IsBegin()))
00372     return false;
00373   if((token.IsEnd() && !token.IsBegin())  && (token.StringValue() == rLabel))
00374     return true; 
00375   std::stringstream errstr;
00376   errstr << "Section End\"" << rLabel << "\" expected at " << FileLine();
00377   throw Exception("TokenReader::Eos", errstr.str(), 51);
00378   return false;
00379 }
00380   
00381 
00382 // ReadInteger()
00383 long int TokenReader::ReadInteger(void) {
00384   Token token;      
00385   Get(token);
00386   if(!token.IsInteger()) {
00387     std::stringstream errstr;
00388     errstr << "Integer expected at " << FileLine();
00389     throw Exception("TokenReader::TokenReader", errstr.str(), 50);
00390   }
00391   return token.IntegerValue();
00392 }
00393 
00394 // ReadFloat()
00395 double TokenReader::ReadFloat(void) {
00396   Token token;      
00397   Get(token);
00398   if((!token.IsFloat()) && (!token.IsInteger())) {
00399     std::stringstream errstr;
00400     errstr << "Float expected at " << FileLine();
00401     throw Exception("TokenReader::TokenReader", errstr.str(), 50);
00402   }
00403   return token.FloatValue();
00404 }
00405 
00406 // ReadString()
00407 const std::string& TokenReader::ReadString(void) {
00408   Token token;      
00409   Get(token);
00410   if(!token.IsString()) {
00411     std::stringstream errstr;
00412     errstr << "Name expected at " << FileLine();
00413     throw Exception("TokenReader::TokenReader", errstr.str(), 50);
00414   }
00415   mLastString=token.StringValue();
00416   return(mLastString);
00417 }
00418 
00419  
00420 // ReadOption()
00421 const std::string& TokenReader::ReadOption(void) {
00422   Token token;      
00423   Get(token);
00424   if(!token.IsOption()) {
00425     std::stringstream errstr;
00426     errstr << "Option expected at " << FileLine();
00427     throw Exception("TokenReader::TokenReader", errstr.str(), 50);
00428   }
00429   mLastString=token.OptionValue();
00430   return(mLastString);
00431 }
00432 
00433 // ReadBinary()
00434 const std::string& TokenReader::ReadBinary(void) {
00435   Token token;      
00436   Get(token);
00437   if(!token.IsBinary()) {
00438     std::stringstream errstr;
00439     errstr << "Binary string expected at " << FileLine();
00440     throw Exception("TokenReader::TokenReader", errstr.str(), 50);
00441   }
00442   mLastString=token.StringValue();
00443   return(mLastString);
00444 }
00445 
00446 
00447 // ReadText()
00448 const std::string& TokenReader::ReadText(void) {
00449   // do my own reading
00450   int ll=Token::ReadEscapedString(mpStream,'<',mLastString);
00451   if(ll<0) {
00452     std::stringstream errstr;
00453     errstr << "Text expected at " << FileLine();
00454     throw Exception("TokenReader::TokenReader", errstr.str(), 50);
00455   }
00456   // strip leading/tailing space
00457   static const std::string white=" \n\t\r\v\f";
00458   unsigned int pos1=mLastString.find_first_not_of(white);
00459   if(pos1!=std::string::npos)  
00460     mLastString=mLastString.substr(pos1);
00461   else
00462     mLastString.clear();
00463   unsigned int pos2=mLastString.find_last_not_of(white);
00464   if(pos2!=std::string::npos)  
00465     mLastString.erase(pos2+1);
00466   // clear peak buffer
00467   mHasPeekToken=false;
00468   mPeekToken.SetNone();
00469   // do linecount
00470   mLineCount+=ll;
00471   return mLastString;
00472 }
00473 
00474  
00475 
00476 // Line()
00477 int TokenReader::Line(void) const {
00478   return mLineCount;
00479 }
00480 
00481 // FileLine()
00482 std::string TokenReader::FileLine(void) const {
00483   if(mFileName!="")
00484     return "("+ mFileName + ":" + ToStringInteger(mLineCount) +")";
00485   else
00486     return "(#" + ToStringInteger(mLineCount) +")";
00487 }
00488 
00489 } // namespace faudes

libFAUDES 2.18b --- 2010-12-17 --- c++ source docu by doxygen 1.6.3