About
User Reference
C++ API
luafaudes
Developer
Links
libFAUDES online
libFAUDES

Sections

Index

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

libFAUDES 2.20d --- 2011.04.26 --- c++ source docu by doxygen