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 
5 Copyright (C) 2006 Bernd Opitz
6 Copyright (C) 2006 Thomas Moor
7 Exclusive copyright is granted to Klaus Schmidt
8 
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
13 
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18 
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22 
23 
24 #include "cfl_tokenwriter.h"
25 
26 namespace faudes {
27 
28 // TokenWriter(rFilename, openmode)
29 TokenWriter::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)
47 TokenWriter::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)
118 TokenWriter::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
147 void TokenWriter::Flush(void) {
148  DoFlush();
149  mpStream->flush();
150  if(mMode==Stdout) {
151  bool m=ConsoleOut::G()->Mute();
152  ConsoleOut::G()->Mute(false);
153  ConsoleOut::G()->Write(mSStream.str());
154  ConsoleOut::G()->Mute(m);
155  mSStream.str("");
156  }
157 }
158 
159 // Str()
160 std::string TokenWriter::Str(void) {
161  if(mMode!=String) {
162  std::stringstream errstr;
163  errstr << "Not in String Mode";
164  throw Exception("TokenWriter::Str()", errstr.str(), 2);
165  }
166  Flush();
167  return mSStream.str();
168 }
169 
170 // Stream()
171 std::ostream* TokenWriter::Streamp(void) {
172  Flush();
173  return mpStream;
174 }
175 
176 
177 
178 // Columns()
179 int TokenWriter::Columns(void) const {
180  return mColumns;
181 }
182 
183 // Columns()
184 void TokenWriter::Columns(int columns) {
185  mColumns = columns;
186 }
187 
188 // Endl()
189 void TokenWriter::Endl(void) {
190  DoFlush();
191  try{
192  if(mEndl) *mpStream << std::endl;
193  else *mpStream << " ";
194  }
195  catch (std::ios::failure&) {
196  std::stringstream errstr;
197  errstr << "Exception opening/writing file \"" << mFileName << "\"";
198  throw Exception("Generator::write", errstr.str(), 2);
199  }
200 }
201 
202 // Endl(bool)
203 void TokenWriter::Endl(bool on) {
204  mEndl=on;
205 }
206 
207 // DoFlush: write buffered token
208 // Note: dont call Endl() since this calls DoFlush
210  if(!mHasOutBuffer) return;
211  FD_DV("TokenWriter::DoFlush()");
212  try{
213  // markup starts a new line: pre linefeed
214  if(mOutBuffer.IsBegin() || mOutBuffer.IsEnd())
215  if(mColCount !=0 && (mColumns>0) && mEndl) {
218  }
219  // columncount starts a new line
220  if(mColCount >= mColumns && (mColumns>0) && mEndl) {
223  }
224  // if we just started a new column, we dont need any seps
225  if(mColCount==0) {
228  }
229  // do the write
231  mColCount++;
232  // count my columns
234  // markup starts a new line: post line feed
235  if(mOutBuffer.IsBegin() || mOutBuffer.IsEnd())
236  if(mColumns>0 && mEndl) {
237  *mpStream << std::endl;
238  mColCount=0;
239  }
240  }
241  catch (std::ios::failure&) {
242  std::stringstream errstr;
243  errstr << "Exception opening/writing file \"" << mFileName << "\"";
244  throw Exception("TokenWriter::Write(token)", errstr.str(), 2);
245  }
246  mHasOutBuffer=false;
247 }
248 
249 // Write(rToken)
250 void TokenWriter::Write(const Token& rToken) {
251  FD_DV("TokenWriter::Write(token)");
252  // figure wether we can merge to an empty section:
253  // 1. buffer begin must match the current token end tag
254  if(rToken.IsEnd() && !rToken.IsBegin())
255  if(mHasOutBuffer)
256  if(mOutBuffer.IsBegin() && !mOutBuffer.IsEnd())
257  if(mOutBuffer.StringValue()==rToken.StringValue())
258  // 2. dont do it on HTML tags since it irritates bowsers
259  if(mOutBuffer.StringValue()!="b")
260  if(mOutBuffer.StringValue()!="i")
261  if(mOutBuffer.StringValue()!="tt")
262  if(mOutBuffer.StringValue()!="p")
263  if(mOutBuffer.StringValue()!="h1")
264  if(mOutBuffer.StringValue()!="h2")
265  if(mOutBuffer.StringValue()!="h3")
266  if(mOutBuffer.StringValue()!="h4")
267  if(mOutBuffer.StringValue()!="font")
268  if(mOutBuffer.StringValue()!="strong")
269  {
271  DoFlush();
272  return;
273  }
274  // figure wether we need a preceeding space
275  bool needsep=true;
276  if(mHasOutBuffer) {
277  if(mOutBuffer.IsBegin()) needsep=false;
278  if(mOutBuffer.IsEnd()) needsep=false;
279  }
280  if(rToken.IsBegin()) needsep=false;
281  if(rToken.IsEnd()) needsep=false;
282  // write buffer if any
283  DoFlush();
284  // record to buffer
285  mOutBuffer=rToken;
287  mHasOutBuffer=true;
288 }
289 
290 
291 // WriteString(rName)
292 void TokenWriter::WriteString(const std::string& rName) {
293  if((rName == "\n") || (rName == "\r\n")) {
294  Endl();
295  mColCount = 0;
296  return;
297  }
298  Token token;
299  token.SetString(rName);
300  Write(token);
301 }
302 
303 
304 // WriteText(rText)
305 void TokenWriter::WriteText(const std::string& rText) {
306  try {
307  DoFlush();
309  }
310  catch (std::ios::failure&) {
311  std::stringstream errstr;
312  errstr << "Exception opening/writing file \"" << mFileName << "\"";
313  throw Exception("TokenWriter::WriteText(text)", errstr.str(), 2);
314  }
315 }
316 
317 // WriteText(rBegin,rText)
318 void TokenWriter::WriteText(const Token& rBeginTag, const std::string& rText) {
319  if(!rBeginTag.IsBegin() || rBeginTag.IsEnd()) {
320  std::stringstream errstr;
321  errstr << "Invalid begin token while writing file \"" << mFileName << "\"";
322  throw Exception("TokenWriter::WriteText(label,text)", errstr.str(), 2);
323  }
324  try {
325  Write(rBeginTag);
326  DoFlush();
328  Endl();
329  WriteEnd(rBeginTag.StringValue());
330  }
331  catch (std::ios::failure&) {
332  std::stringstream errstr;
333  errstr << "Exception writing file \"" << mFileName << "\"";
334  throw Exception("TokenWriter::WriteText(label,text)", errstr.str(), 2);
335  }
336 }
337 
338 
339 // WriteText(rLabel,rText)
340 void TokenWriter::WriteText(const std::string& rLabel, const std::string& rText) {
341  Token btag;
342  btag.SetBegin(rLabel);
343  WriteText(btag,rText);
344 }
345 
346 
347 // WriteCharacterData(rCData)
348 void TokenWriter::WriteCharacterData(const std::string& rCharacterData) {
349  try {
350  DoFlush();
351  *mpStream << rCharacterData;
352  }
353  catch (std::ios::failure&) {
354  std::stringstream errstr;
355  errstr << "Exception opening/writing file \"" << mFileName << "\"";
356  throw Exception("TokenWriter::WriteCharacterData(text)", errstr.str(), 2);
357  }
358 }
359 
360 // WriteVerbatim(rData)
361 void TokenWriter::WriteVerbatim(const std::string& rData) {
362  FD_DV("TokenWriter::Write(token)");
363  // if(mMode==Stdout) mpStream = &std::cout; // fix
364  DoFlush();
365  try{
366  if(mColCount !=0) Endl();
368  mColCount = 0;
369  }
370  catch (std::ios::failure&) {
371  std::stringstream errstr;
372  errstr << "Exception opening/writing file \"" << mFileName << "\"";
373  throw Exception("TokenWriter::WriteVerbatim()", errstr.str(), 2);
374  }
375 }
376 
377 // WriteInteger(index)
379  Token token;
380  token.SetInteger(index);
381  Write(token);
382 }
383 
384 // WriteInteger(index)
385 void TokenWriter::WriteInteger16(long int val) {
386  Token token;
387  token.SetInteger16(val);
388  Write(token);
389 }
390 
391 // WriteFloat(float)
392 void TokenWriter::WriteFloat(const double& val) {
393  Token token;
394  token.SetFloat(val);
395  Write(token);
396 }
397 
398 
399 // WriteOption(rOpt)
400 void TokenWriter::WriteOption(const std::string& rOpt) {
401  Token token;
402  token.SetOption(rOpt);
403  Write(token);
404 }
405 
406 
407 // WriteBegin(rLabel)
408 void TokenWriter::WriteBegin(const std::string& rLabel) {
409  Token token;
410  token.SetBegin(rLabel);
411  Write(token);
412 }
413 
414 // WriteEnd(rLabel)
415 void TokenWriter::WriteEnd(const std::string& rLabel) {
416  Token token;
417  token.SetEnd(rLabel);
418  Write(token);
419 }
420 
421 // WriteBegin(rLabel)
422 void TokenWriter::WriteEmpty(const std::string& rLabel) {
423  Token token;
424  token.SetEmpty(rLabel);
425  Write(token);
426 }
427 
428 // WriteComment(comment)
429 void TokenWriter::WriteComment(const std::string& comment){
430  DoFlush();
431  // auto xml
432  if(mMode==XmlFile || mMode==XmlStream) { WriteXmlComment(comment); return; }
433  // no endl ... no comment
434  if(!mEndl) return;
435  try{
436  if(mColCount!=0) Endl();
437  // fix comment indicator
438  if(comment.length()==0)
439  *mpStream << "% ";
440  if(comment.length()>0)
441  if(comment.at(0)!='%')
442  *mpStream << "% ";
443  // xml/endl escape
444  std::string::const_iterator cit=comment.begin();
445  for(;cit!=comment.end(); cit++) {
446  if(*cit=='<')
447  { *mpStream << "&lt;"; continue;}
448  if(*cit=='>')
449  { *mpStream << "&gt;"; continue;}
450  if(*cit=='&')
451  { *mpStream << "&amp;"; continue;}
452  if(*cit=='\n')
453  { *mpStream << " "; continue;}
454  if(*cit=='\r')
455  { ; continue;}
456  *mpStream << *cit;
457  }
458  // done
459  Endl();
460  mColCount = 0;
461  }
462  catch (std::ios::failure&) {
463  std::stringstream errstr;
464  errstr << "Exception opening/writing file \"" << mFileName << "\"";
465  throw Exception("TokenWriter::Comment", errstr.str(), 2);
466  }
467 }
468 
469 // WriteXmlComment(comment)
470 void TokenWriter::WriteXmlComment(const std::string& comment){
471  if(!mEndl) return; // no endl implies no comments
472  DoFlush();
473  try{
474  if(mColCount!=0) Endl();
475  // begin tag
476  *mpStream << "<!-- ";
477  // test for multiline
478  static const std::string newline="\n\r";
479  if(comment.find_first_of(newline)!=std::string::npos)
480  Endl();
481  // xml/endl escape
482  std::string::const_iterator cit=comment.begin();
483  for(;cit!=comment.end(); cit++) {
484  if(*cit=='>')
485  { *mpStream << "&gt;"; continue;}
486  *mpStream << *cit;
487  }
488  // end tag
489  *mpStream << " -->";
490  // done
491  Endl();
492  mColCount = 0;
493  }
494  catch (std::ios::failure&) {
495  std::stringstream errstr;
496  errstr << "Exception opening/writing file \"" << mFileName << "\"";
497  throw Exception("TokenWriter::Comment", errstr.str(), 2);
498  }
499 }
500 
501 // write base64
502 void TokenWriter::WriteBinary(const char* pData, long int len) {
503  DoFlush();
504  Token::WriteBinary(mpStream,pData,len);
505 }
506 
507 // FileName()
508 std::string TokenWriter::FileName(void) const {
509  return mFileName;
510 }
511 
512 
513 
514 
515 } // namespace faudes

libFAUDES 2.24g --- 2014.09.15 --- c++ api documentaion by doxygen