cfl_tokenwriter.cppGo 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 << "<"; continue;} 00448 if(*cit=='>') 00449 { *mpStream << ">"; continue;} 00450 if(*cit=='&') 00451 { *mpStream << "&"; 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 << ">"; 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 |