cfl_tokenwriter.cpp
Go to the documentation of this file.
1/** @file cfl_tokenwriter.cpp @brief Class TokenWriter */
2
3/* FAU Discrete Event Systems Library (libfaudes)
4
5Copyright (C) 2006 Bernd Opitz
6Copyright (C) 2006, 2010, 2024 Thomas Moor
7Exclusive copyright is granted to Klaus Schmidt
8
9This library is free software; you can redistribute it and/or
10modify it under the terms of the GNU Lesser General Public
11License as published by the Free Software Foundation; either
12version 2.1 of the License, or (at your option) any later version.
13
14This library is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public
20License along with this library; if not, write to the Free Software
21Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23
24#include "cfl_tokenwriter.h"
25
26namespace faudes {
27
28// TokenWriter(rFilename, openmode)
29TokenWriter::TokenWriter(const std::string& rFilename, std::ios::openmode openmode)
30 : mMode(File), pSStream(0), mHasOutBuffer(false), mFileName(rFilename), mColumns(80/FD_NAMELEN), mColCount(0) {
31 // set up mFStream
32 mFStream.exceptions(std::ios::badbit|std::ios::failbit);
33 try{
34 mFStream.open(rFilename.c_str(), openmode);
35 }
36 catch (std::ios::failure&) {
37 std::stringstream errstr;
38 errstr << "Exception opening/writing file \""<< rFilename << "\"";
39 throw Exception("TokenWriter::TokenWriter", errstr.str(), 2);
40 }
41 // use mFStream
43 mEndl=true;
44}
45
46// TokenWriter(rFilename, doctype)
47TokenWriter::TokenWriter(const std::string& rFilename, const std::string& ftype)
48 : mMode(XmlFile), pSStream(0), mHasOutBuffer(false), mFileName(rFilename), mColumns(80/FD_NAMELEN), mColCount(0) {
49 // set up mFStream
50 mFStream.exceptions(std::ios::badbit|std::ios::failbit);
51 try{
52 mFStream.open(rFilename.c_str(), std::ios::out|std::ios::trunc);
53 mFStream << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" standalone=\"no\"?>" << std::endl;
54 if(ftype!="")
55 if(ftype!="Void") {
56 std::string dtdfile=ftype;
57 std::transform(dtdfile.begin(), dtdfile.end(), dtdfile.begin(), tolower);
58 dtdfile="http://www.faudes.org/dtd/1.0/"+dtdfile+".dtd";
59 mFStream << "<!DOCTYPE " << ftype << " SYSTEM \"" << dtdfile << "\">" << std::endl;
60 }
61 }
62 catch (std::ios::failure&) {
63 std::stringstream errstr;
64 errstr << "Exception opening/writing xml file \""<< rFilename << "\"";
65 throw Exception("TokenWriter::TokenWriter", errstr.str(), 2);
66 }
67 // use mFStream
69 mEndl=true;
70}
71
72// TokenWriter(mode)
74 : mMode(mode), pSStream(0), mHasOutBuffer(false), mFileName(""), mColumns(80/FD_NAMELEN), mColCount(0) {
75 switch(mode) {
76 case Stdout:
77 // set up mFStream
78 /*
79 try {
80 mFStream.copyfmt(std::cout);
81 mFStream.clear(std::cout.rdstate());
82 typedef std::basic_ios<char> ___basic_ios_char_; // trick for vc++
83 mFStream.___basic_ios_char_::rdbuf(std::cout.rdbuf());
84 }
85 catch (std::ios::failure&) {
86 std::stringstream errstr;
87 errstr << "Exception opening/writing file \""<< mFileName << "\"";
88 throw Exception("TokenWriter::TokenWriter", errstr.str(), 2);
89 }
90 // use mFStream
91 mpStream=&mFStream;
92 */
93 // use std::cout
94 /*
95 mpStream= &std::cout;
96 mEndl=true;
97 */
98 // use mSStream to buffer and write to faudes ConsoleOut
99 mFileName="stdout";
101 mEndl=true;
102 break;
103 case String:
104 // use mSStream
105 mFileName="string";
107 mEndl=false;
108 break;
109 default:
110 std::stringstream errstr;
111 errstr << "Invalid Mode / Not Implemented";
112 throw Exception("TokenWriter::TokenWriter", errstr.str(), 2);
113 }
114}
115
116
117// TokenWriter(stream)
118TokenWriter::TokenWriter(std::ostream& stream, const std::string& ftype)
119 : mMode(Stream), pSStream(&stream), mHasOutBuffer(false), mFileName("stream"), mColumns(0), mColCount(0) {
120 // xml if there is a doctype
121 try {
122 if(ftype!="")
123 if(ftype!="Void") {
124 std::string dtdfile=ftype;
125 std::transform(dtdfile.begin(), dtdfile.end(), dtdfile.begin(), tolower);
126 dtdfile="http://www.faudes.org/dtd/1.0/"+dtdfile+".dtd";
127 *pSStream << "<!DOCTYPE " << ftype << " SYSTEM \"" << dtdfile << "\">" << std::endl;
129 }
130 } catch (std::ios::failure&) {
131 std::stringstream errstr;
132 errstr << "Exception opening/writing xml stream";
133 throw Exception("TokenWriter::TokenWriter", errstr.str(), 2);
134 }
135 // use provided stream
137 mEndl=true;
138}
139
140// destructor
142 Flush();
143 if(mMode==File) mFStream.close();
144}
145
146// Flush buffers
148 DoFlush(); // incl linefeed if col>0
149 mpStream->flush();
150 if(mMode==Stdout) {
151 ConsoleOut::G()->Write(mSStream.str(),0,0,0); // verb 0 <> always
152 mSStream.str("");
153 }
154}
155
156// Str()
157std::string TokenWriter::Str(void) {
158 if(mMode!=String) {
159 std::stringstream errstr;
160 errstr << "Not in String Mode";
161 throw Exception("TokenWriter::Str()", errstr.str(), 2);
162 }
163 Flush();
164 return mSStream.str();
165}
166
167// Stream()
168std::ostream* TokenWriter::Streamp(void) {
169 DoFlush(0); // no extra formating
170 return mpStream;
171}
172
173
174
175// Columns()
176int TokenWriter::Columns(void) const {
177 return mColumns;
178}
179
180// Columns()
181void TokenWriter::Columns(int columns) {
182 mColumns = columns;
183}
184
185// Endl()
187 DoFlush(1);
188 try{
189 if(mEndl) *mpStream << std::endl;
190 else *mpStream << " ";
191 }
192 catch (std::ios::failure&) {
193 std::stringstream errstr;
194 errstr << "Exception opening/writing file \"" << mFileName << "\"";
195 throw Exception("Generator::write", errstr.str(), 2);
196 }
197}
198
199// Endl(bool)
200void TokenWriter::Endl(bool on) {
201 mEndl=on;
202}
203
204// DoFlush: write buffered token
205// Note: dont call Endl() since this calls DoFlush
206void TokenWriter::DoFlush(bool clf) {
207 if(!mHasOutBuffer) return;
208 FD_DV("TokenWriter::DoFlush()");
209 try{
210 // write preceeding space
211 for(size_t i=0; i< mOutBuffer.mPreceedingSpace.size(); ++i) {
212 char c= mOutBuffer.mPreceedingSpace.at(i);
213 if(c=='\n') {
214 if(mEndl) *mpStream << std::endl;
215 else *mpStream << " ";
216 mColCount=0; ;
217 continue;
218 }
219 if(c=='\r') continue;
220 if(isspace(c)) mpStream->put(c);
221 }
222 // do the write
224 // count my columns
225 mColCount++;
226 // have closing linefeed for true flush
227 if(clf) {
229 if(mColCount==1)
230 if(mEndl) { *mpStream << std::endl; mColCount=0;}
232 }
233 }
234 catch (std::ios::failure&) {
235 std::stringstream errstr;
236 errstr << "Exception opening/writing file \"" << mFileName << "\"";
237 throw Exception("TokenWriter::Write(token)", errstr.str(), 2);
238 }
239 mHasOutBuffer=false;
240}
241
242// Write(rToken)
244 FD_DV("TokenWriter::Write(token)");
245 // figure wether we can merge to an empty section:
246 // 1. buffer begin must match the current token end tag
247 if(rToken.IsEnd() && !rToken.IsBegin())
248 if(mHasOutBuffer)
250 if(mOutBuffer.StringValue()==rToken.StringValue())
251 // 2. dont do it on HTML tags since it irritates bowsers
252 if(mOutBuffer.StringValue()!="b")
253 if(mOutBuffer.StringValue()!="i")
254 if(mOutBuffer.StringValue()!="tt")
255 if(mOutBuffer.StringValue()!="p")
256 if(mOutBuffer.StringValue()!="h1")
257 if(mOutBuffer.StringValue()!="h2")
258 if(mOutBuffer.StringValue()!="h3")
259 if(mOutBuffer.StringValue()!="h4")
260 if(mOutBuffer.StringValue()!="font")
261 if(mOutBuffer.StringValue()!="strong")
262 {
264 DoFlush(0);
265 return;
266 }
267 // flush buffer
268 if(mHasOutBuffer) DoFlush(0);
269 // prefer markup in new line before
270 if(rToken.PreceedingSpace()=="")
271 if(rToken.IsBegin() || rToken.IsEnd())
272 if(mColCount > 0)
273 rToken.PreceedingSpace("\n");
274 // prefer markup in new line after
275 if(rToken.PreceedingSpace()=="")
277 if(mColCount == 1)
278 rToken.PreceedingSpace("\n");
279 // columncount proposes linefeed
280 if(rToken.PreceedingSpace()=="")
281 if(mColCount >= mColumns && (mColumns>0) && mEndl) {
282 rToken.mPreceedingSpace="\n";
283 }
284 // insist in space between data tokens
285 if(rToken.PreceedingSpace()=="")
286 if(!(rToken.IsBegin()) && (!rToken.IsEnd()))
287 if(!(mOutBuffer.IsBegin()) && (!mOutBuffer.IsEnd())) {
288 rToken.mPreceedingSpace=" ";
289 }
290 // record token to buffer
291 mOutBuffer=rToken;
292 mHasOutBuffer=true;
293}
294
295
296// WriteString(rName)
297void TokenWriter::WriteString(const std::string& rName) {
298 if((rName == "\n") || (rName == "\r\n")) {
299 Endl();
300 mColCount = 0;
301 return;
302 }
303 Token token;
304 token.SetString(rName);
305 Write(token);
306}
307
308
309// WriteText(rText) --- depreciated, use below variants
310void TokenWriter::WriteText(const std::string& rText) {
311 try {
312 DoFlush();
314 }
315 catch (std::ios::failure&) {
316 std::stringstream errstr;
317 errstr << "Exception opening/writing file \"" << mFileName << "\"";
318 throw Exception("TokenWriter::WriteText(text)", errstr.str(), 2);
319 }
320}
321
322// WriteText(rBegin,rText)
323void TokenWriter::WriteText(Token& rBeginTag, const std::string& rText) {
324 if(!rBeginTag.IsBegin() || rBeginTag.IsEnd()) {
325 std::stringstream errstr;
326 errstr << "Invalid begin token while writing file \"" << mFileName << "\"";
327 throw Exception("TokenWriter::WriteText(label,text)", errstr.str(), 2);
328 }
329 try {
330 Write(rBeginTag);
331 Flush();
333 Endl();
334 WriteEnd(rBeginTag.StringValue());
335 }
336 catch (std::ios::failure&) {
337 std::stringstream errstr;
338 errstr << "Exception writing file \"" << mFileName << "\"";
339 throw Exception("TokenWriter::WriteText(label,text)", errstr.str(), 2);
340 }
341}
342
343
344// WriteText(rLabel,rText) -- wrapper
345void TokenWriter::WriteText(const std::string& rLabel, const std::string& rText) {
346 Token btag;
347 btag.SetBegin(rLabel);
348 WriteText(btag,rText);
349}
350
351
352// WriteVerbatim(rData)
353void TokenWriter::WriteVerbatim(Token& rBeginTag, const std::string& rText) {
354 FD_DV("TokenWriter::Write(token)");
355 if(!rBeginTag.IsBegin() || rBeginTag.IsEnd()) {
356 std::stringstream errstr;
357 errstr << "Invalid begin token while writing file \"" << mFileName << "\"";
358 throw Exception("TokenWriter::WriteVerbatim(tag,text)", errstr.str(), 2);
359 }
360 Write(rBeginTag);
361 Flush();
362 try{
363 if(mColCount !=0) Endl();
364 Token::WriteVerbatim(mpStream,rText,1); // flag: add linefeeds
365 mColCount = 0;
366 Endl();
367 }
368 catch (std::ios::failure&) {
369 std::stringstream errstr;
370 errstr << "Exception opening/writing file \"" << mFileName << "\"";
371 throw Exception("TokenWriter::WriteVerbatim()", errstr.str(), 2);
372 }
373 WriteEnd(rBeginTag.StringValue());
374}
375
376// WriteVerbatim(rLabel,rText) -- wrapper
377void TokenWriter::WriteVerbatim(const std::string& rLabel, const std::string& rText) {
378 Token btag;
379 btag.SetBegin(rLabel);
380 WriteVerbatim(btag,rText);
381}
382
383
384// WriteCharacterData(rCData)
385void TokenWriter::WriteCharacterData(const std::string& rCharacterData) {
386 // bail out on trivial to avoid unnecessary flush
387 if(rCharacterData.size()==0) return;
388 // do write
389 try {
390 DoFlush(0); // no extra linefeed formating here
391 *mpStream << rCharacterData;
392 }
393 catch (std::ios::failure&) {
394 std::stringstream errstr;
395 errstr << "Exception opening/writing file \"" << mFileName << "\"";
396 throw Exception("TokenWriter::WriteCharacterData(text)", errstr.str(), 2);
397 }
398 // adjust column count
400 if(rCharacterData.size()>=1)
401 if(rCharacterData.at(rCharacterData.size()-1)=='\n')
402 mColCount=0;
403}
404
405// WriteInteger(index)
407 Token token;
408 token.SetInteger(index);
409 Write(token);
410}
411
412// WriteInteger(index)
413void TokenWriter::WriteInteger16(long int val) {
414 Token token;
415 token.SetInteger16(val);
416 Write(token);
417}
418
419// WriteFloat(float)
420void TokenWriter::WriteFloat(const double& val) {
421 Token token;
422 token.SetFloat(val);
423 Write(token);
424}
425
426
427// WriteOption(rOpt)
428void TokenWriter::WriteOption(const std::string& rOpt) {
429 Token token;
430 token.SetOption(rOpt);
431 Write(token);
432}
433
434
435// WriteBegin(rLabel)
436void TokenWriter::WriteBegin(const std::string& rLabel) {
437 Token token;
438 token.SetBegin(rLabel);
439 Write(token);
440}
441
442// WriteEnd(rLabel)
443void TokenWriter::WriteEnd(const std::string& rLabel) {
444 Token token;
445 token.SetEnd(rLabel);
446 Write(token);
447}
448
449// WriteBegin(rLabel)
450void TokenWriter::WriteEmpty(const std::string& rLabel) {
451 Token token;
452 token.SetEmpty(rLabel);
453 Write(token);
454}
455
456// WriteComment(comment)
457void TokenWriter::WriteComment(const std::string& comment){
458 DoFlush();
459 // auto xml
460 if(mMode==XmlFile || mMode==XmlStream) { WriteXmlComment(comment); return; }
461 // no endl ... no comment
462 if(!mEndl) return;
463 try{
464 if(mColCount!=0) Endl();
465 // fix comment indicator
466 if(comment.length()==0)
467 *mpStream << "% ";
468 if(comment.length()>0)
469 if(comment.at(0)!='%')
470 *mpStream << "% ";
471 // xml/endl escape
472 std::string::const_iterator cit=comment.begin();
473 for(;cit!=comment.end(); cit++) {
474 if(*cit=='<')
475 { *mpStream << "&lt;"; continue;}
476 if(*cit=='>')
477 { *mpStream << "&gt;"; continue;}
478 if(*cit=='&')
479 { *mpStream << "&amp;"; continue;}
480 if(*cit=='\n')
481 { *mpStream << " "; continue;}
482 if(*cit=='\r')
483 { ; continue;}
484 *mpStream << *cit;
485 }
486 // done
487 Endl();
488 mColCount = 0;
489 }
490 catch (std::ios::failure&) {
491 std::stringstream errstr;
492 errstr << "Exception opening/writing file \"" << mFileName << "\"";
493 throw Exception("TokenWriter::Comment", errstr.str(), 2);
494 }
495}
496
497// WriteXmlComment(comment)
498void TokenWriter::WriteXmlComment(const std::string& comment){
499 if(!mEndl) return; // no endl implies no comments
500 DoFlush();
501 try{
502 if(mColCount!=0) Endl();
503 // begin tag
504 *mpStream << "<!-- ";
505 // test for multiline
506 static const std::string newline="\n\r";
507 if(comment.find_first_of(newline)!=std::string::npos)
508 Endl();
509 // xml/endl escape
510 std::string::const_iterator cit=comment.begin();
511 for(;cit!=comment.end(); cit++) {
512 if(*cit=='>')
513 { *mpStream << "&gt;"; continue;}
514 *mpStream << *cit;
515 }
516 // end tag
517 *mpStream << " -->";
518 // done
519 Endl();
520 mColCount = 0;
521 }
522 catch (std::ios::failure&) {
523 std::stringstream errstr;
524 errstr << "Exception opening/writing file \"" << mFileName << "\"";
525 throw Exception("TokenWriter::Comment", errstr.str(), 2);
526 }
527}
528
529// write base64
530void TokenWriter::WriteBinary(const char* pData, long int len) {
531 DoFlush();
532 Token::WriteBinary(mpStream,pData,len);
533}
534
535// FileName()
536std::string TokenWriter::FileName(void) const {
537 return mFileName;
538}
539
540
541
542
543} // namespace faudes
#define FD_NAMELEN
#define FD_DV(message)
Class TokenWriter.
static ConsoleOut * G(void)
virtual void Write(const std::string &message, long int cntnow=0, long int cntdone=0, int verb=1)
void WriteInteger16(long int val)
std::ostringstream mSStream
std::string FileName(void) const
std::string Str(void)
void WriteFloat(const double &val)
void WriteXmlComment(const std::string &rComment)
std::ostream * mpStream
void WriteText(const std::string &rText)
void WriteEmpty(const std::string &rLabel)
void WriteCharacterData(const std::string &rCharData)
void WriteComment(const std::string &rComment)
void Write(Token &rToken)
std::ostream * Streamp(void)
void WriteString(const std::string &rString)
std::ostream * pSStream
void WriteEnd(const std::string &rLabel)
void WriteBinary(const char *pData, long int len)
int Columns(void) const
void WriteVerbatim(Token &rBeginTag, const std::string &rText)
void DoFlush(bool clf=1)
void WriteInteger(Idx index)
void WriteBegin(const std::string &rLabel)
void WriteOption(const std::string &rOpt)
void SetNone(void)
Definition cfl_token.cpp:73
const std::string & PreceedingSpace(void) const
void SetInteger16(const Int number)
const std::string & StringValue(void) const
void SetInteger(const Int number)
@ End
<\label> (end of section)
Definition cfl_token.h:85
static void WriteVerbatim(std::ostream *pStream, const std::string &rString, bool lfflag=0)
void Write(std::ostream *pStream) const
void SetString(const std::string &rName)
Definition cfl_token.cpp:85
void SetOption(const std::string &rName)
bool IsBegin(void) const
void SetFloat(const faudes::Float number)
void SetEmpty(const std::string &rName)
static void WriteBinary(std::ostream *pStream, const char *pData, std::size_t len)
static int WriteEscapedString(std::ostream *pStream, const std::string &outstr)
void SetBegin(const std::string &rName)
Definition cfl_token.cpp:92
bool IsEnd(void) const
std::string mPreceedingSpace
Definition cfl_token.h:649
void SetEnd(const std::string &rName)
Definition cfl_token.cpp:99
uint32_t Idx

libFAUDES 2.33k --- 2025.09.16 --- c++ api documentaion by doxygen