cfl_helper.cpp
Go to the documentation of this file.
1 /** @file cfl_helper.cpp Helper functions */
2 
3 /* FAU Discrete Event Systems Library (libfaudes)
4 
5  Copyright (C) 2006 Bernd Opitz
6  Copyright (C) 2008-2010 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 
25 
26 #include "cfl_helper.h"
27 
28 
29 // Debug includes
30 #include "cfl_attributes.h"
31 #include "cfl_registry.h"
32 #include "cfl_types.h"
33 #include "cfl_elementary.h"
34 
35 
36 // c++ file io
37 #include <fstream>
38 
39 
40 namespace faudes {
41 
42 // ToStringInteger(number)
43 std::string ToStringInteger(long int number) {
44  if(number>= std::numeric_limits<long int>::max()) return "inf";
45  if(number<= std::numeric_limits<long int>::min()+1) return "-inf";
46  std::string res;
47  std::stringstream sstr;
48  sstr << number;
49  sstr >> res;
50  return res;
51 }
52 
53 // ToStringInteger16(number)
54 std::string ToStringInteger16(long int number) {
55  std::string res;
56  std::stringstream sstr;
57  sstr << "0x" << std::setbase(16) << number;
58  sstr >> res;
59  return res;
60 }
61 
62 // ToStringFloat(number)
63 // todo: check range, prevent sci notation
64 std::string ToStringFloat(double number) {
65  if(number == (long int) number)
66  return(ToStringInteger((long int) number));
67  std::string res;
68  std::stringstream sstr;
69  sstr << std::fixed;
70  sstr << number;
71  sstr >> res;
72  return res;
73 }
74 
75 // ExpandString(rString, len)
76 std::string ExpandString(const std::string& rString, unsigned int len) {
77  std::string res;
78  res = rString;
79  std::string::size_type xtra = (std::string::size_type) len - rString.length();
80  if ((xtra > 0) && (xtra < 10000)) {
81  res.append(xtra, ' ');
82  }
83  return res;
84 }
85 
86 // CollapseString(rString, len)
87 std::string CollapsString(const std::string& rString, unsigned int len) {
88  if(len <=1) return rString;
89  if(rString.length() <= len) return rString;
90  int chead = len/2;
91  int ctail = len-chead;
92  return rString.substr(0,chead) + "..." + rString.substr(rString.length()-ctail,ctail);
93 }
94 
95 // ToIdx(rString)
96 Idx ToIdx(const std::string& rString) {
97  char * end;
98  unsigned long ul = strtoul (rString.c_str(), &end, 0);
99  unsigned long idxmax = std::numeric_limits<Idx>::max();
100  if(ul > idxmax) {
101  throw Exception("atoidx", "Idx overflow", 600);
102  }
103  return (Idx) ul;
104 }
105 
106 // String Substitution
107 std::string StringSubstitute(const std::string& rString,const std::string& rFrom,const std::string& rTo) {
108  // prep result
109  std::string res;
110  std::size_t pos=0;
111  // loop over occurences of "from"
112  while(pos<rString.length()) {
113  std::size_t next=rString.find(rFrom,pos);
114  if(next==std::string::npos) break;
115  res.append(rString.substr(pos, next-pos));
116  res.append(rTo);
117  pos=next+rFrom.length();
118  }
119  // get end
120  if(pos<rString.length())
121  res.append(rString.substr(pos));
122  // done
123  return res;
124 }
125 
126 // VersionString()
127 std::string VersionString() {
128  return std::string(FAUDES_VERSION);
129 }
130 
131 // FDPluginsString()
132 std::string PluginsString() {
133  return std::string(FAUDES_PLUGINS);
134 }
135 
136 // FDContributorsString()
137 std::string ContributorsString() {
138  return
139  "Ramon Barakat, Ruediger Berndt, Christian Breindl, Christine Baier, Tobias Barthel, Christoph Doerr, Marc Duevel, Norman Franchi, Rainer Hartmann, Jochen Hellenschmidt, Stefan Jacobi, Matthias Leinfelder, Tomas Masopust, Michael Meyer, Andreas Mohr, Thomas Moor, Mihai Musunoi, Bernd Opitz, Irmgard Petzoldt, Sebastian Perk, Thomas Rempel, Daniel Ritter, Berno Schlein, Ece Schmidt, Klaus Schmidt, Anne-Kathrin Schmuck, Sven Schneider, Matthias Singer, Ulas Turan, Christian Wamser, Zhengying Wang, Thomas Wittmann, Shi Xiaoxun, Jorgos Zaddach, et al";
140 }
141 
142 
143 // ProcessDot(infile,outfile,format)
144 void ProcessDot(const std::string& rDotFile,
145  const std::string& rOutFile, const std::string& rOutFormat, const std::string& rDotExec)
146 {
147  std::string format=rOutFormat;
148  // guess format from filename
149  if(format=="") {
150  if(rOutFile.rfind('.')+1 < rOutFile.size()) {
151  format=rOutFile.substr(rOutFile.rfind('.')+1);
152  }
153  }
154  // test format
155  if (format == "canon");
156  else if (format == "dot");
157  else if (format == "xdot");
158  else if (format == "cmap");
159  else if (format == "dia");
160  else if (format == "fig");
161  else if (format == "gd");
162  else if (format == "gd2");
163  else if (format == "gif");
164  else if (format == "hpgl");
165  else if (format == "imap");
166  else if (format == "cmapx");
167  else if (format == "ismap");
168  else if (format == "jpg");
169  else if (format == "jpeg");
170  else if (format == "mif");
171  else if (format == "mp");
172  else if (format == "pcl");
173  else if (format == "pic");
174  else if (format == "plain");
175  else if (format == "plain-ext");
176  else if (format == "png");
177  else if (format == "ps");
178  else if (format == "ps2");
179  else if (format == "svg");
180  else if (format == "svgz");
181  else if (format == "vrml");
182  else if (format == "vtx");
183  else if (format == "wbmp");
184  else if (format == "eps");
185  else if (format == "pdf");
186  else {
187  std::stringstream errstr;
188  errstr << "Dot output format \"" << format << "\" unknown";
189  throw Exception("faudes::ProcessDot", errstr.str(), 3);
190  }
191  std::string dotcommand = rDotExec + " -T"+format+" \""+rDotFile+"\" -o \""+rOutFile+"\"";
192  if(system(dotcommand.c_str()) != 0) {
193  throw Exception("faudes::ProcessDot",
194  "Error in running " + dotcommand, 3);
195  }
196 }
197 
198 
199 // CreateTempFile(void)
200 // todo: sys dependant, report, investigate threads
201 std::string CreateTempFile(void) {
202  char filename[]= "faudes_temp_XXXXXX";
203  std::string res;
204 #ifdef FAUDES_POSIX
205  // use mkstemp on recent Posix systems
206  int filedes = -1;
207  filedes= mkstemp(filename);
208  if(filedes==-1) {
209  FD_DF("faudes::CreateTempFile(): error");
210  return res;
211  }
212  close(filedes);
213  res=std::string(filename);
214 #endif
215 #ifdef FAUDES_WINDOWS
216  // mimique mkstemp on Windows/MinGW
217  /*
218  int filedes = -1;
219  #define _S_IREAD 256
220  #define _S_IWRITE 128
221  mktemp(filename);
222  filedes=open(filename,O_RDWR|O_BINARY|O_CREAT|O_EXCL|_O_SHORT_LIVED, _S_IREAD|_S_IWRITE);
223  if(filedes==-1) {
224  FD_DF("faudes::CreateTempFile(): error");
225  return "";
226  }
227  close(filedes);
228  res=std::string(filename);
229  */
230  // win32 API
231  char* tmpname = _mktemp(filename);
232  FILE* file;
233  if(tmpname==NULL) {
234  FD_DF("faudes::CreateTempFile(): error");
235  return res;
236  }
237  fopen_s(&file,tmpname,"w");
238  if(file==NULL) {
239  FD_DF("faudes::CreateTempFile(): error");
240  return "";
241  }
242  fclose(file);
243  res=std::string(tmpname);
244 #endif
245  FD_DF("faudes::CreateTempFile(): " << res);
246  return(res);
247 }
248 
249 
250 // RemoveFile(void)
251 // todo: sys dependant *
252 bool RemoveFile(const std::string& rFileName) {
253  return std::remove(rFileName.c_str()) == 0;
254 }
255 
256 
257 // ExtractPath
258 std::string ExtractDirectory(const std::string& rFullPath) {
259  std::string res="";
260  std::size_t seppos = rFullPath.find_last_of(faudes_pathseps());
261  if(seppos==std::string::npos) return res;
262  res=rFullPath.substr(0,seppos+1);
263  return res;
264 }
265 
266 // ExtractFilename
267 std::string ExtractFilename(const std::string& rFullPath) {
268  std::string res=rFullPath;
269  std::size_t seppos = rFullPath.find_last_of(faudes_pathseps());
270  if(seppos==std::string::npos) return res;
271  res=rFullPath.substr(seppos+1);
272  return res;
273 }
274 
275 // ExtractBasename
276 std::string ExtractBasename(const std::string& rFullPath) {
277  std::string res=rFullPath;
278  std::size_t seppos = res.find_last_of(faudes_pathseps());
279  if(seppos!=std::string::npos) {
280  res=res.substr(seppos+1);
281  }
282  std::size_t dotpos = res.find_last_of(".");
283  if(dotpos!=std::string::npos) {
284  res=res.substr(0,dotpos);
285  }
286  return res;
287 }
288 
289 // ExtractExtension
290 std::string ExtractExtension(const std::string& rFullPath) {
291  std::string res=rFullPath;
292  std::size_t seppos = res.find_last_of(faudes_pathseps());
293  if(seppos!=std::string::npos) {
294  res=res.substr(seppos+1);
295  }
296  std::size_t dotpos = res.find_last_of(".");
297  if(dotpos!=std::string::npos)
298  if(dotpos +1 < res.size()) {
299  return res.substr(dotpos+1,res.size()-dotpos-1);
300  }
301  return std::string();
302 }
303 
304 // PrependPath
305 std::string PrependDirectory(const std::string& rDirectory, const std::string& rFileName) {
306  std::string res=rDirectory;
307  char sepchar=faudes_pathsep().at(0);
308  if(res!="")
309  if(res.at(res.length()-1)!=sepchar)
310  res.append(1,sepchar);
311  res.append(rFileName);
312  return res;
313 }
314 
315 // Test directory
316 bool DirectoryExists(const std::string& rDirectory) {
317 #ifdef FAUDES_POSIX
318  DIR *thedir;
319  thedir=opendir(rDirectory.c_str());
320  if(thedir) closedir(thedir);
321  return thedir!= 0;
322 #endif
323 #ifdef FAUDES_WINDOWS
324  DWORD fattr = GetFileAttributesA(rDirectory.c_str());
325  return
326  (fattr!=INVALID_FILE_ATTRIBUTES) && (fattr & FILE_ATTRIBUTE_DIRECTORY);
327 #endif
328  return false;
329 }
330 
331 // scan directory
332 std::set< std::string > ReadDirectory(const std::string& rDirectory) {
333  std::set< std::string > res;
334 #ifdef FAUDES_POSIX
335  DIR *thedir;
336  struct dirent *theent;
337  thedir=opendir(rDirectory.c_str());
338  if(!thedir) return res;
339  while((theent=readdir(thedir))) {
340  std::string fname(theent->d_name);
341  if(fname==".") continue;
342  if(fname=="..") continue;
343  res.insert(fname);
344  }
345  closedir(thedir);
346 #endif
347 #ifdef FAUDES_WINDOWS
348  HANDLE hf;
349  WIN32_FIND_DATA data;
350  hf = FindFirstFile((rDirectory+"\\*.*").c_str(), &data);
351  if (hf != INVALID_HANDLE_VALUE) {
352  do {
353  std::string fname(data.cFileName);
354  if(fname==".") continue;
355  if(fname=="..") continue;
356  res.insert(fname);
357  } while (FindNextFile(hf, &data));
358  FindClose(hf);
359  }
360 #endif
361  return res;
362 }
363 
364 
365 
366 
367 
368 // Test file
369 bool FileExists(const std::string& rFilename) {
370  std::fstream fp;
371  fp.open(rFilename.c_str(), std::ios::in | std::ios::binary);
372  return fp.good();
373 }
374 
375 // Delete file
376 bool FileDelete(const std::string& rFilename) {
377  return remove(rFilename.c_str()) == 0;
378 }
379 
380 // Copy file
381 bool FileCopy(const std::string& rFromFile, const std::string& rToFile) {
382  std::ifstream froms(rFromFile.c_str(), std::ios::binary);
383  std::ofstream tos(rToFile.c_str(), std::ios::binary);
384  tos << froms.rdbuf();
385  tos.flush();
386  return !(froms.fail() || tos.fail());
387 }
388 
389 // ConsoleOut class
390 // Note: console-out is not re-entrant; for multithreaded applications
391 // you must derive a class that has built-in mutexes;
392 ConsoleOut::ConsoleOut(void) : pStream(NULL), mMute(false) {
393  pInstance=this;
394 }
396  if(pStream) { pStream->flush(); delete pStream; }
397  if(this==smpInstance) smpInstance=NULL;
398 }
400  if(!smpInstance) smpInstance= new ConsoleOut();
401  return smpInstance->pInstance;
402 }
404  std::string fname = smpInstance->pInstance->Filename();
406  smpInstance->pInstance=out;
408  smpInstance->pInstance->ToFile(fname);
409 }
410 void ConsoleOut::ToFile(const std::string& filename) {
411  if(pStream) { pStream->flush(); delete pStream; }
412  pStream=NULL;
413  mFilename=filename;
414  if(mFilename=="") return;
415  pStream = new std::ofstream();
416  pStream->open(mFilename.c_str(),std::ios::app);
417 }
418 void ConsoleOut::Write(const std::string& message,long int cntnow, long int cntdone) {
419  if(mMute) return;
420  DoWrite(message,cntnow,cntdone);
421 }
422 void ConsoleOut::DoWrite(const std::string& message,long int cntnow, long int cntdone) {
423  (void) cntnow; (void) cntdone;
424  std::ostream* sout=pStream;
425  if(!sout) sout=&std::cout; // tmoor: used to be std::cerr, using std::cout to facilitate emscripten/js
426  *sout << message;
427  sout->flush();
428 }
429 
430 // global instance
432 
433 
434 
435 // debugging: objectcount
436 std::map<std::string,long int>* ObjectCount::mspMax=NULL;
437 std::map<std::string,long int>* ObjectCount::mspCount=NULL;
438 bool ObjectCount::msDone=false;
440  mspCount= new std::map<std::string,long int>();
441  mspMax= new std::map<std::string,long int>();
442  msDone=true;
443 }
444 void ObjectCount::Init(void) {
445  if(!msDone) ObjectCount();
446 }
447 void ObjectCount::Inc(const std::string& rTypeName) {
448  if(!msDone) ObjectCount();
449  long int cnt = ((*mspCount)[rTypeName]+=1);
450  if((*mspMax)[rTypeName]<cnt) (*mspMax)[rTypeName]=cnt;
451 }
452 void ObjectCount::Dec(const std::string& rTypeName) {
453  if(!msDone) ObjectCount();
454  (*mspCount)[rTypeName]-=1;
455 }
456 
457 
458 // debugging: report on exit function
459 void ExitFunction(void){
460 #ifdef FAUDES_DEBUG_CODE
461  FAUDES_WRITE_CONSOLE("faudes::ExitFunction():");
462  // be sure its up and running
464  // get rid of all registry prototypes
465  //TypeRegistry::G()->ClearAll();
466  //FunctionRegistry::G()->Clear();
467  // prepare report
468  std::map<std::string,long int>::iterator cit;
469  cit=ObjectCount::mspCount->begin();
470  for(;cit!=ObjectCount::mspCount->end();cit++) {
471  FAUDES_WRITE_CONSOLE( cit->first << ": #" << ToStringInteger(cit->second) <<
472  " (max #" << (*ObjectCount::mspMax)[cit->first] << ")");
473  }
474 #endif
475 }
476 
477 
478 #ifdef FAUDES_DEBUG_CODE
479 // report on exit install
480 class ExitFunctionInstall {
481 private:
482  static bool mDone;
483  static ExitFunctionInstall mInstance;
484  ExitFunctionInstall(void) {
485  if(mDone) return;
486  FAUDES_WRITE_CONSOLE("ExitFunctionInstall()");
487  std::atexit(ExitFunction);
488  mDone=true;
489  }
490 };
491 // exit function: global data
492 bool ExitFunctionInstall::mDone=false;
493 ExitFunctionInstall ExitFunctionInstall::mInstance;
494 #endif
495 
496 // test protocol: token writer and file
498 std::string gTestProtocolFr;
499 
500 // test protocol: setup
501 std::string TestProtocol(const std::string& rSource) {
502  if(gTestProtocolTw) return gTestProtocolFr;
503  // set up filename
504  std::string filename=rSource;
505  // fix empty source
506  if(filename=="") filename="faudes_dump";
507  // remove directory
508  filename=ExtractFilename(filename);
509  // remove extension
510  std::string::size_type pos=0;
511  for(;pos<filename.length();pos++)
512  if(filename.at(pos)=='.') filename.at(pos)='_';
513  // append extension
514  filename.append(".prot");
515  // record nominal case
516  gTestProtocolFr=filename;
517  // prepend prefix
518  filename.insert(0,"tmp_");
519  // initialise token writer
520  gTestProtocolTw= new TokenWriter(filename);
521  // report filename
522  return gTestProtocolFr;
523 }
524 
525 // test protocol: dump
526 void TestProtocol(const std::string& rMessage, const Type& rData, bool full) {
527  if(!gTestProtocolTw) return;
528  gTestProtocolTw->WriteComment("%%% test mark: " + rMessage);
529  if(full) rData.Write(*gTestProtocolTw);
530  else rData.SWrite(*gTestProtocolTw);
534  *gTestProtocolTw << "\n";
535 }
536 void TestProtocol(const std::string& rMessage, bool data) {
537  Boolean fbool(data);
538  TestProtocol(rMessage,fbool,true);
539 }
540 void TestProtocol(const std::string& rMessage, long int data) {
541  Integer fint(data);
542  TestProtocol(rMessage,fint,true);
543 }
544 void TestProtocol(const std::string& rMessage, const std::string& rData) {
545  String fstr(rData);
546  TestProtocol(rMessage,fstr,true);
547 }
548 
549 // test protocol: compare
550 bool TestProtocol(void) {
551  // bail out on no protocol
552  if(!gTestProtocolTw) return true;
553  // close protocol file
554  std::string prot=gTestProtocolTw->FileName();
555  delete gTestProtocolTw;
556  gTestProtocolTw=NULL;
557  // open protocol
558  std::fstream fp;
559  fp.open(prot.c_str(), std::ios::in | std::ios::binary);
560  if(!fp.good()) {
561  FAUDES_WRITE_CONSOLE("TestProtocol(): could not open protocol \"" << prot << "\"");
562  return false;
563  }
564  // open reference
565  std::string ref=gTestProtocolFr;
566  std::fstream fr;
567  fr.open(ref.c_str(), std::ios::in | std::ios::binary);
568  if(!fr.good()) {
569  ref="data"+faudes_pathsep()+ref;
570  fr.clear(); // mingw's runtime will not clear on open
571  fr.open(ref.c_str(), std::ios::in | std::ios::binary);
572  }
573  if(!fr.good()) {
574  FAUDES_WRITE_CONSOLE("TestProtocol(): could not open/find reference \"" << gTestProtocolFr << "\"");
575  return true;
576  }
577  // perform comparision
578  int dline=-1;
579  int cline=1;
580  try{
581  while(true) {
582  // read next char
583  char cp = fp.get();
584  char cr= fr.get();
585  // eof
586  if(fp.eof() && fr.eof()) { break; }
587  if(!fp.good() || !fr.good()) { dline=cline; break;}
588  // cheap normalize cr/lf: ignore \r (assume no double \r
589  if( cp=='\r' && cr =='\r') continue;
590  if( cp=='\r' && fp.eof()){ dline=cline; break;}
591  if( cp=='\r') cp = fp.get();
592  if( cr=='\r' && fr.eof()){ dline=cline; break;}
593  if( cr=='\r') cr = fr.get();
594  // count lines
595  if( cr=='\n') cline++;
596  // sense mitmatch
597  if( cp!= cr ){dline=cline; break;}
598  }
599  } catch(std::ios::failure&) {
600  throw Exception("TestProtocol()", "io error at line " + ToStringInteger(cline), 1);
601  }
602  // done
603  if(dline>=0) {
604  FAUDES_WRITE_CONSOLE("TestProtocol(): using reference " << ref << "");
605  FAUDES_WRITE_CONSOLE("TestProtocol(): found difference at line " << dline << "");
606  }
607  return dline== -1;
608 }
609 
610 
611 
612 // declare loop callback
613 static bool (*gBreakFnct)(void)=0;
614 
615 // set loop callback
616 void LoopCallback( bool pBreak(void)) {
617  gBreakFnct=pBreak;
618 }
619 
620 // do loop callback
621 // note: this function is meant to be "quiet" during normal
622 // operation in order not to mess up console logging
623 void LoopCallback(void){
624  if(!gBreakFnct) return;
625  if(! (*gBreakFnct)() ) return;
626  throw Exception("LoopCallback", "break on application request", 110);
627 }
628 
629 } // namespace faudes

libFAUDES 2.26g --- 2015.08.17 --- c++ api documentaion by doxygen