About
User Reference
C++ API
luafaudes
Developer
Links
libFAUDES online
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_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.20s --- 2011.10.12 --- c++ source docu by doxygen