cfl_tokenwriter.cpp

Go to the documentation of this file.
00001 /** @file cfl_tokenwriter.cpp @brief Class TokenWriter */
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 #include "cfl_tokenwriter.h"
00025 
00026 namespace faudes {
00027 
00028 // TokenWriter(rFilename, openmode)
00029 TokenWriter::TokenWriter(const std::string& rFilename, std::ios::openmode openmode) 
00030   : mMode(File), pSStream(0), mHasOutBuffer(false), mFileName(rFilename), mColumns(80/FD_NAMELEN), mColCount(0) {
00031   // set up mFStream
00032   mFStream.exceptions(std::ios::badbit|std::ios::failbit);
00033   try{
00034     mFStream.open(rFilename.c_str(), openmode); 
00035   }
00036   catch (std::ios::failure&) {
00037     std::stringstream errstr;
00038     errstr << "Exception opening/writing file \""<< rFilename << "\"";
00039     throw Exception("TokenWriter::TokenWriter", errstr.str(), 2);
00040   }
00041   // use mFStream
00042   mpStream=&mFStream;      
00043   mEndl=true;
00044 }
00045 
00046 // TokenWriter(rFilename, doctype)
00047 TokenWriter::TokenWriter(const std::string& rFilename, const std::string& ftype) 
00048   : mMode(XmlFile), pSStream(0), mHasOutBuffer(false), mFileName(rFilename), mColumns(80/FD_NAMELEN), mColCount(0) {
00049   // set up mFStream
00050   mFStream.exceptions(std::ios::badbit|std::ios::failbit);
00051   try{
00052     mFStream.open(rFilename.c_str(), std::ios::out|std::ios::trunc); 
00053     mFStream << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" standalone=\"no\"?>" << std::endl;
00054     if(ftype!="") 
00055     if(ftype!="Void") {
00056       std::string dtdfile=ftype;
00057       std::transform(dtdfile.begin(), dtdfile.end(), dtdfile.begin(), tolower);
00058       dtdfile="http://www.faudes.org/dtd/1.0/"+dtdfile+".dtd";
00059       mFStream << "<!DOCTYPE " << ftype << " SYSTEM \"" << dtdfile << "\">" << std::endl;
00060     }
00061   }
00062   catch (std::ios::failure&) {
00063     std::stringstream errstr;
00064     errstr << "Exception opening/writing xml file \""<< rFilename << "\"";
00065     throw Exception("TokenWriter::TokenWriter", errstr.str(), 2);
00066   }
00067   // use mFStream
00068   mpStream=&mFStream;      
00069   mEndl=true;
00070 }
00071 
00072 // TokenWriter(mode)
00073 TokenWriter::TokenWriter(Mode mode)
00074   : mMode(mode), pSStream(0), mHasOutBuffer(false), mFileName(""), mColumns(80/FD_NAMELEN), mColCount(0) {
00075   switch(mode) {
00076   case Stdout: 
00077     // set up mFStream
00078     /*
00079       try {
00080       mFStream.copyfmt(std::cout);
00081       mFStream.clear(std::cout.rdstate());
00082       typedef std::basic_ios<char> ___basic_ios_char_; // trick for vc++
00083       mFStream.___basic_ios_char_::rdbuf(std::cout.rdbuf());
00084       }
00085       catch (std::ios::failure&) {
00086       std::stringstream errstr;
00087       errstr << "Exception opening/writing file \""<< mFileName << "\"";
00088       throw Exception("TokenWriter::TokenWriter", errstr.str(), 2);
00089       }
00090       // use mFStream
00091       mpStream=&mFStream;
00092     */
00093     // use std::cout
00094     /*
00095     mpStream= &std::cout;
00096     mEndl=true;
00097     */
00098     // use mSStream to buffer and write to faudes ConsoleOut
00099     mFileName="stdout";
00100     mpStream=&mSStream;
00101     mEndl=true;
00102     break;
00103   case String:
00104     // use mSStream
00105     mFileName="string";
00106     mpStream=&mSStream;
00107     mEndl=false;
00108     break;
00109   default:
00110     std::stringstream errstr;
00111     errstr << "Invalid Mode / Not Implemented";
00112     throw Exception("TokenWriter::TokenWriter", errstr.str(), 2);
00113   }
00114 }
00115 
00116 
00117 // TokenWriter(stream)
00118 TokenWriter::TokenWriter(std::ostream& stream, const std::string& ftype) 
00119   : mMode(Stream), pSStream(&stream), mHasOutBuffer(false), mFileName("stream"), mColumns(0), mColCount(0) {
00120   // xml if there is a doctype
00121   try {
00122     if(ftype!="") 
00123     if(ftype!="Void") {
00124       std::string dtdfile=ftype;
00125       std::transform(dtdfile.begin(), dtdfile.end(), dtdfile.begin(), tolower);
00126       dtdfile="http://www.faudes.org/dtd/1.0/"+dtdfile+".dtd";
00127       *pSStream << "<!DOCTYPE " << ftype << " SYSTEM \"" << dtdfile << "\">" << std::endl;
00128       mMode=XmlStream;
00129     }
00130   } catch (std::ios::failure&) {
00131     std::stringstream errstr;
00132     errstr << "Exception opening/writing xml stream";
00133     throw Exception("TokenWriter::TokenWriter", errstr.str(), 2);
00134   }
00135   // use provided stream
00136   mpStream=pSStream;      
00137   mEndl=true;
00138 }
00139 
00140 // destructor
00141 TokenWriter::~TokenWriter(void) {
00142   Flush();
00143   if(mMode==File) mFStream.close();
00144 }
00145 
00146 // Flush buffers
00147 void TokenWriter::Flush(void) {
00148   DoFlush();
00149   mpStream->flush();
00150   if(mMode==Stdout) {
00151     bool m=ConsoleOut::G()->Mute();
00152     ConsoleOut::G()->Mute(false);
00153     ConsoleOut::G()->Write(mSStream.str());
00154     ConsoleOut::G()->Mute(m);
00155     mSStream.str("");
00156   }
00157 }
00158 
00159 // Str()
00160 std::string TokenWriter::Str(void) {
00161   if(mMode!=String) {
00162     std::stringstream errstr;
00163     errstr << "Not in String Mode";
00164     throw Exception("TokenWriter::Str()", errstr.str(), 2);
00165   }
00166   Flush();
00167   return mSStream.str();
00168 }
00169 
00170 // Stream()
00171 std::ostream* TokenWriter::Streamp(void) {
00172   Flush();
00173   return mpStream;
00174 }
00175 
00176 
00177 
00178 // Columns()
00179 int TokenWriter::Columns(void) const {
00180   return mColumns;
00181 }
00182 
00183 // Columns()
00184 void TokenWriter::Columns(int columns) {
00185   mColumns = columns;
00186 }
00187 
00188 // Endl()
00189 void TokenWriter::Endl(void) {
00190   DoFlush();
00191   try{
00192     if(mEndl) *mpStream << std::endl;
00193     else *mpStream << " ";
00194   }
00195   catch (std::ios::failure&) {
00196     std::stringstream errstr;
00197     errstr << "Exception opening/writing file \"" << mFileName << "\"";
00198     throw Exception("Generator::write", errstr.str(), 2);
00199   }
00200 }
00201 
00202 // Endl(bool)
00203 void TokenWriter::Endl(bool on) {
00204   mEndl=on;
00205 }
00206 
00207 // DoFlush: write buffered token
00208 // Note: dont call Endl() since this calls DoFlush
00209 void TokenWriter::DoFlush(void) {
00210   if(!mHasOutBuffer) return;
00211   FD_DV("TokenWriter::DoFlush()");
00212   try{
00213     // markup starts a new line: pre linefeed
00214     if(mOutBuffer.IsBegin() || mOutBuffer.IsEnd()) 
00215     if(mColCount !=0 && (mColumns>0) && mEndl) {
00216       mOutBuffer.mPreceedingNewline=true;
00217       mOutBuffer.mPreceedingSpace=false;
00218     }
00219     // columncount starts a new line
00220     if(mColCount >= mColumns && (mColumns>0) && mEndl) {
00221       mOutBuffer.mPreceedingNewline=true;
00222       mOutBuffer.mPreceedingSpace=false;
00223     }
00224     // if we just started a new column, we dont need any seps
00225     if(mColCount==0) {
00226       mOutBuffer.mPreceedingNewline=false;
00227       mOutBuffer.mPreceedingSpace=false;
00228     }
00229     // do the write
00230     mOutBuffer.Write(mpStream);
00231     mColCount++;
00232     // count my columns
00233     if(mOutBuffer.mPreceedingNewline) mColCount =1;
00234     // markup starts a new line: post line feed
00235     if(mOutBuffer.IsBegin() || mOutBuffer.IsEnd()) 
00236     if(mColumns>0 && mEndl) {
00237        *mpStream << std::endl;
00238        mColCount=0;
00239     }
00240   }
00241   catch (std::ios::failure&) {
00242     std::stringstream errstr;
00243     errstr << "Exception opening/writing file \"" << mFileName << "\"";
00244     throw Exception("TokenWriter::Write(token)", errstr.str(), 2);
00245   }
00246   mHasOutBuffer=false;
00247 }
00248 
00249 // Write(rToken)
00250 void TokenWriter::Write(const Token& rToken) {
00251   FD_DV("TokenWriter::Write(token)");
00252   // figure wether we can merge to an empty section:
00253   // 1. buffer begin must match the current token end tag
00254   if(rToken.IsEnd() && !rToken.IsBegin()) 
00255   if(mHasOutBuffer) 
00256   if(mOutBuffer.IsBegin() && !mOutBuffer.IsEnd())
00257   if(mOutBuffer.StringValue()==rToken.StringValue()) 
00258   // 2. dont do it on HTML tags since it irritates bowsers
00259   if(mOutBuffer.StringValue()!="b")
00260   if(mOutBuffer.StringValue()!="i")
00261   if(mOutBuffer.StringValue()!="tt")
00262   if(mOutBuffer.StringValue()!="p")
00263   if(mOutBuffer.StringValue()!="h1")
00264   if(mOutBuffer.StringValue()!="h2")
00265   if(mOutBuffer.StringValue()!="h3")
00266   if(mOutBuffer.StringValue()!="h4")
00267   if(mOutBuffer.StringValue()!="font")
00268   if(mOutBuffer.StringValue()!="strong")
00269   {
00270     mOutBuffer.mType |= Token::End;
00271     DoFlush();
00272     return;
00273   }
00274   // figure wether we need a preceeding space
00275   bool needsep=true;
00276   if(mHasOutBuffer) {  
00277     if(mOutBuffer.IsBegin()) needsep=false;
00278     if(mOutBuffer.IsEnd()) needsep=false;
00279   }
00280   if(rToken.IsBegin()) needsep=false;
00281   if(rToken.IsEnd()) needsep=false;
00282   // write buffer if any
00283   DoFlush();
00284   // record to buffer
00285   mOutBuffer=rToken;
00286   mOutBuffer.mPreceedingSpace = mOutBuffer.mPreceedingSpace || needsep;
00287   mHasOutBuffer=true;
00288 }
00289 
00290 
00291 // WriteString(rName)
00292 void TokenWriter::WriteString(const std::string& rName) {
00293   if((rName == "\n") || (rName == "\r\n")) {
00294     Endl();
00295     mColCount = 0;
00296     return;
00297   }
00298   Token token;
00299   token.SetString(rName);
00300   Write(token);
00301 }
00302 
00303 
00304 // WriteText(rText)
00305 void TokenWriter::WriteText(const std::string& rText) {
00306   try {
00307     DoFlush();
00308     Token::WriteEscapedString(mpStream,rText);
00309   } 
00310   catch (std::ios::failure&) {
00311     std::stringstream errstr;
00312     errstr << "Exception opening/writing file \"" << mFileName << "\"";
00313     throw Exception("TokenWriter::WriteText(text)", errstr.str(), 2);
00314   }
00315 }
00316 
00317 // WriteText(rBegin,rText)
00318 void TokenWriter::WriteText(const Token& rBeginTag, const std::string& rText) {
00319   if(!rBeginTag.IsBegin() || rBeginTag.IsEnd()) {
00320     std::stringstream errstr;
00321     errstr << "Invalid begin token while writing file \"" << mFileName << "\"";
00322     throw Exception("TokenWriter::WriteText(label,text)", errstr.str(), 2);
00323   }
00324   try {
00325     Write(rBeginTag);
00326     DoFlush();
00327     Token::WriteEscapedString(mpStream,rText);
00328     Endl();
00329     WriteEnd(rBeginTag.StringValue());
00330   } 
00331   catch (std::ios::failure&) {
00332     std::stringstream errstr;
00333     errstr << "Exception writing file \"" << mFileName << "\"";
00334     throw Exception("TokenWriter::WriteText(label,text)", errstr.str(), 2);
00335   }
00336 }
00337 
00338 
00339 // WriteText(rLabel,rText)
00340 void TokenWriter::WriteText(const std::string& rLabel, const std::string& rText) {
00341   Token btag;
00342   btag.SetBegin(rLabel);
00343   WriteText(btag,rText);
00344 }
00345 
00346 
00347 // WriteCharacterData(rCData)
00348 void TokenWriter::WriteCharacterData(const std::string& rCharacterData) {
00349   try {
00350     DoFlush();
00351     *mpStream << rCharacterData;
00352   } 
00353   catch (std::ios::failure&) {
00354     std::stringstream errstr;
00355     errstr << "Exception opening/writing file \"" << mFileName << "\"";
00356     throw Exception("TokenWriter::WriteCharacterData(text)", errstr.str(), 2);
00357   }
00358 }
00359 
00360 // WriteVerbatim(rData)
00361 void TokenWriter::WriteVerbatim(const std::string& rData) {
00362   FD_DV("TokenWriter::Write(token)");
00363   // if(mMode==Stdout) mpStream = &std::cout; // fix
00364   DoFlush();
00365   try{
00366     if(mColCount !=0) Endl();
00367     Token::WriteVerbatim(mpStream,rData);
00368     mColCount = 0;
00369   }
00370   catch (std::ios::failure&) {
00371     std::stringstream errstr;
00372     errstr << "Exception opening/writing file \"" << mFileName << "\"";
00373     throw Exception("TokenWriter::WriteVerbatim()", errstr.str(), 2);
00374   }
00375 }
00376 
00377 // WriteInteger(index)
00378 void TokenWriter::WriteInteger(Idx index) {
00379   Token token;
00380   token.SetInteger(index);
00381   Write(token);
00382 }
00383 
00384 // WriteInteger(index)
00385 void TokenWriter::WriteInteger16(long int val) {
00386   Token token;
00387   token.SetInteger16(val);
00388   Write(token);
00389 }
00390 
00391 // WriteFloat(float)
00392 void TokenWriter::WriteFloat(const double& val) {
00393   Token token;
00394   token.SetFloat(val);
00395   Write(token);
00396 }
00397 
00398 
00399 // WriteOption(rOpt)
00400 void TokenWriter::WriteOption(const std::string& rOpt) {
00401   Token token;
00402   token.SetOption(rOpt);
00403   Write(token);
00404 }
00405 
00406 
00407 // WriteBegin(rLabel)
00408 void TokenWriter::WriteBegin(const std::string& rLabel) {
00409   Token token;
00410   token.SetBegin(rLabel);
00411   Write(token);
00412 }
00413 
00414 // WriteEnd(rLabel)
00415 void TokenWriter::WriteEnd(const std::string& rLabel) {
00416   Token token;
00417   token.SetEnd(rLabel);
00418   Write(token);
00419 }
00420 
00421 // WriteBegin(rLabel)
00422 void TokenWriter::WriteEmpty(const std::string& rLabel) {
00423   Token token;
00424   token.SetEmpty(rLabel);
00425   Write(token);
00426 }
00427 
00428 // WriteComment(comment)
00429 void TokenWriter::WriteComment(const std::string& comment){
00430   DoFlush();
00431   // auto xml 
00432   if(mMode==XmlFile || mMode==XmlStream) { WriteXmlComment(comment); return; }
00433   // no endl ... no comment
00434   if(!mEndl) return; 
00435   try{
00436     if(mColCount!=0)  Endl();
00437     // fix comment indicator
00438     if(comment.length()==0) 
00439       *mpStream << "% ";
00440     if(comment.length()>0) 
00441     if(comment.at(0)!='%')
00442       *mpStream << "% ";
00443     // xml/endl escape
00444     std::string::const_iterator cit=comment.begin(); 
00445     for(;cit!=comment.end(); cit++) {
00446       if(*cit=='<') 
00447         { *mpStream << "&lt;"; continue;}
00448       if(*cit=='>') 
00449         { *mpStream << "&gt;"; continue;}
00450       if(*cit=='&') 
00451        { *mpStream << "&amp;"; continue;}
00452       if(*cit=='\n') 
00453        { *mpStream << " "; continue;}
00454       if(*cit=='\r') 
00455        { ; continue;}
00456       *mpStream << *cit;
00457     }
00458     // done
00459     Endl();
00460     mColCount = 0;
00461   }
00462   catch (std::ios::failure&) {
00463     std::stringstream errstr;
00464     errstr << "Exception opening/writing file \"" << mFileName << "\"";
00465     throw Exception("TokenWriter::Comment", errstr.str(), 2);
00466   }
00467 }
00468 
00469 // WriteXmlComment(comment)
00470 void TokenWriter::WriteXmlComment(const std::string& comment){
00471   if(!mEndl) return; //  no endl implies no comments
00472   DoFlush();
00473   try{
00474     if(mColCount!=0)  Endl();
00475     // begin tag
00476     *mpStream << "<!-- ";
00477     // test for multiline
00478     static const std::string newline="\n\r";
00479     if(comment.find_first_of(newline)!=std::string::npos) 
00480       Endl();
00481     // xml/endl escape
00482     std::string::const_iterator cit=comment.begin(); 
00483     for(;cit!=comment.end(); cit++) {
00484       if(*cit=='>') 
00485         { *mpStream << "&gt;"; continue;}
00486       *mpStream << *cit;
00487     }
00488     // end tag
00489     *mpStream << " -->";
00490     // done
00491     Endl();
00492     mColCount = 0;
00493   }
00494   catch (std::ios::failure&) {
00495     std::stringstream errstr;
00496     errstr << "Exception opening/writing file \"" << mFileName << "\"";
00497     throw Exception("TokenWriter::Comment", errstr.str(), 2);
00498   }
00499 }
00500 
00501 // write base64
00502 void TokenWriter::WriteBinary(const char* pData, long int len) {
00503   DoFlush();
00504   Token::WriteBinary(mpStream,pData,len);
00505 }
00506 
00507 // FileName()
00508 std::string TokenWriter::FileName(void) const {
00509   return mFileName;
00510 }
00511 
00512 
00513 
00514 
00515 } // namespace faudes

libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen