cfl_helper.cpp

Go to the documentation of this file.
00001 /** @file cfl_helper.cpp   Helper functions */
00002 
00003 /* FAU Discrete Event Systems Library (libfaudes)
00004 
00005    Copyright (C) 2006  Bernd Opitz
00006    Copyright (C) 2008-2010 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 
00025 
00026 #include "cfl_helper.h"
00027 
00028 
00029 // Debug includes
00030 #include "cfl_attributes.h"
00031 #include "cfl_registry.h"
00032 #include "cfl_types.h"
00033 #include "cfl_elementary.h"
00034 
00035 // Need posix dirent 
00036 #include <dirent.h>
00037 
00038 // c++ file io
00039 #include <fstream>
00040 
00041 
00042 namespace faudes {
00043 
00044 // ToStringInteger(number)
00045 std::string ToStringInteger(long int number) { 
00046   if(number>= std::numeric_limits<long int>::max()) return "inf";
00047   if(number<= std::numeric_limits<long int>::min()+1) return "-inf";
00048   std::string res;
00049   std::stringstream sstr;
00050   sstr << number;
00051   sstr >> res;
00052   return res;
00053 }
00054 
00055 // ToStringInteger16(number)
00056 std::string ToStringInteger16(long int number) { 
00057    std::string res;
00058    std::stringstream sstr;
00059    sstr << "0x" << std::setbase(16) << number;
00060    sstr >> res;
00061    return res;
00062 }
00063 
00064 // ToStringFloat(number)
00065 // todo: check range, prevent sci notation
00066 std::string ToStringFloat(double number) { 
00067    if(number == (long int) number) 
00068      return(ToStringInteger((long int) number));
00069    std::string res;
00070    std::stringstream sstr;
00071    sstr << std::fixed;
00072    sstr << number;
00073    sstr >> res;
00074    return res;
00075 }
00076 
00077 // ExpandString(rString, len) 
00078 std::string ExpandString(const std::string& rString, unsigned int len) {
00079   std::string res;
00080   res = rString;
00081   std::string::size_type xtra = (std::string::size_type) len - rString.length();
00082   if ((xtra > 0) && (xtra < 10000)) {
00083     res.append(xtra, ' ');
00084   }
00085   return res;
00086 } 
00087 
00088 // CollapseString(rString, len) 
00089 std::string  CollapsString(const std::string& rString, unsigned int len) {
00090   if(len <=1) return rString;
00091   if(rString.length() <= len) return rString;
00092   int chead = len/2;
00093   int ctail = len-chead;
00094   return rString.substr(0,chead) + "..." + rString.substr(rString.length()-ctail,ctail);
00095 } 
00096 
00097 // ToIdx(rString)
00098 Idx ToIdx(const std::string& rString) {
00099   char * end;
00100   unsigned long ul = strtoul (rString.c_str(), &end, 0);
00101   unsigned long idxmax = std::numeric_limits<Idx>::max();
00102   if(ul > idxmax) {
00103     throw Exception("atoidx", "Idx overflow", 600);
00104   }
00105   return (Idx) ul;
00106 }
00107 
00108 // String Substitution
00109 std::string StringSubstitute(const std::string& rString,const std::string& rFrom,const std::string& rTo) {
00110   // prep result
00111   std::string res;
00112   std::size_t pos=0; 
00113   // loop over occurences of "from"
00114   while(pos<rString.length()) {
00115     std::size_t next=rString.find(rFrom,pos);
00116     if(next==std::string::npos) break;
00117     res.append(rString.substr(pos, next-pos));
00118     res.append(rTo);
00119     pos=next+rFrom.length();
00120   }
00121   // get end
00122   if(pos<rString.length()) 
00123     res.append(rString.substr(pos));
00124   // done
00125   return res;
00126 }
00127 
00128 // VersionString()
00129 std::string VersionString() {
00130   return std::string(FAUDES_VERSION);
00131 }
00132 
00133 // FDPluginsString()
00134 std::string PluginsString() {
00135   return std::string(FAUDES_PLUGINS);
00136 }
00137 
00138 // FDContributorsString()
00139 std::string ContributorsString() {
00140   return 
00141     "Ruediger Berndt, Christian Breindl, Christine Baier, Tobias Barthel, Christoph Doerr, Marc Duevel, Norman Franchi, Rainer Hartmann, Jochen Hellenschmidt, Stefan Jacobi, Tomas Masopust, 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";
00142 }
00143 
00144 
00145 // ProcessDot(infile,outfile,format)
00146 void ProcessDot(const std::string& rDotFile, 
00147   const std::string& rOutFile, const std::string& rOutFormat, const std::string& rDotExec)
00148 {
00149   std::string format=rOutFormat;
00150   // guess format from filename
00151   if(format=="") {
00152     if(rOutFile.rfind('.')+1 < rOutFile.size()) {
00153        format=rOutFile.substr(rOutFile.rfind('.')+1);
00154     }
00155   }  
00156   // test format
00157   if (format == "canon"); 
00158   else if (format == "dot"); 
00159   else if (format == "xdot"); 
00160   else if (format == "cmap");
00161   else if (format == "dia");
00162   else if (format == "fig"); 
00163   else if (format == "gd"); 
00164   else if (format == "gd2"); 
00165   else if (format == "gif"); 
00166   else if (format == "hpgl"); 
00167   else if (format == "imap"); 
00168   else if (format == "cmapx");
00169   else if (format == "ismap"); 
00170   else if (format == "jpg"); 
00171   else if (format == "jpeg"); 
00172   else if (format == "mif"); 
00173   else if (format == "mp"); 
00174   else if (format == "pcl"); 
00175   else if (format == "pic"); 
00176   else if (format == "plain"); 
00177   else if (format == "plain-ext"); 
00178   else if (format == "png"); 
00179   else if (format == "ps"); 
00180   else if (format == "ps2"); 
00181   else if (format == "svg"); 
00182   else if (format == "svgz"); 
00183   else if (format == "vrml"); 
00184   else if (format == "vtx"); 
00185   else if (format == "wbmp"); 
00186   else if (format == "eps"); 
00187   else if (format == "pdf"); 
00188   else {
00189     std::stringstream errstr;
00190     errstr << "Dot output format \"" << format << "\" unknown";
00191     throw Exception("faudes::ProcessDot", errstr.str(), 3);
00192   }
00193   std::string dotcommand = rDotExec + " -T"+format+" \""+rDotFile+"\" -o \""+rOutFile+"\"";
00194   if(system(dotcommand.c_str()) != 0) {
00195     throw Exception("faudes::ProcessDot", 
00196         "Error in running " + dotcommand, 3);
00197   }
00198 }
00199 
00200 
00201 // CreateTempFile(void)
00202 // todo: sys dependant, report, investigate threads
00203 std::string CreateTempFile(void) {
00204   char filename[]= "faudes_temp_XXXXXX";
00205   int filedes = -1;
00206 #ifdef FAUDES_POSIX
00207   // use mkstemp on recent Posix systems
00208   filedes= mkstemp(filename);
00209 #endif
00210 #ifdef FAUDES_WINDOWS
00211   // mimique mkstemp on Windows/MinGW
00212   #define _S_IREAD 256
00213   #define _S_IWRITE 128
00214   mktemp(filename); 
00215   filedes=open(filename,O_RDWR|O_BINARY|O_CREAT|O_EXCL|_O_SHORT_LIVED, _S_IREAD|_S_IWRITE); 
00216 #endif
00217   if(filedes==-1) {
00218     FD_DF("faudes::CreateTempFile(): error");
00219     return "";
00220   }
00221   close(filedes);
00222   std::string res(filename);
00223   FD_DF("faudes::CreateTempFile(): " << res);
00224   return(res);
00225 }
00226 
00227 
00228 // RemoveFile(void)
00229 // todo: sys dependant *
00230 bool RemoveFile(const std::string& rFileName) {
00231   return std::remove(rFileName.c_str()) == 0;
00232 }
00233 
00234 
00235 // ExtractPath
00236 std::string ExtractDirectory(const std::string& rFullPath) {
00237   std::string res="";
00238   std::size_t seppos = rFullPath.find_last_of(faudes_pathseps());
00239   if(seppos==std::string::npos) return res;
00240   res=rFullPath.substr(0,seppos+1);
00241   return res;
00242 }
00243 
00244 // ExtractFilename
00245 std::string ExtractFilename(const std::string& rFullPath) {
00246   std::string res=rFullPath;
00247   std::size_t seppos = rFullPath.find_last_of(faudes_pathseps());
00248   if(seppos==std::string::npos) return res;
00249   res=rFullPath.substr(seppos+1);
00250   return res;
00251 }
00252 
00253 // ExtractBasename
00254 std::string ExtractBasename(const std::string& rFullPath) {
00255   std::string res=rFullPath;
00256   std::size_t seppos = res.find_last_of(faudes_pathseps());
00257   if(seppos!=std::string::npos) {
00258     res=res.substr(seppos+1);
00259   }
00260   std::size_t dotpos = res.find_last_of(".");
00261   if(dotpos!=std::string::npos) {
00262     res=res.substr(0,dotpos);
00263   }
00264   return res;
00265 }
00266 
00267 // ExtractExtension
00268 std::string ExtractExtension(const std::string& rFullPath) {
00269   std::string res=rFullPath;
00270   std::size_t seppos = res.find_last_of(faudes_pathseps());
00271   if(seppos!=std::string::npos) {
00272     res=res.substr(seppos+1);
00273   }
00274   std::size_t dotpos = res.find_last_of(".");
00275   if(dotpos!=std::string::npos) 
00276   if(dotpos +1 < res.size()) {
00277     return res.substr(dotpos+1,res.size()-dotpos-1);
00278   }
00279   return std::string();
00280 }
00281 
00282 // PrependPath
00283 std::string PrependDirectory(const std::string& rDirectory, const std::string& rFileName) {
00284   std::string res=rDirectory;
00285   char sepchar=faudes_pathsep().at(0);
00286   if(res!="")
00287   if(res.at(res.length()-1)!=sepchar)
00288     res.append(1,sepchar);
00289   res.append(rFileName);
00290   return res;
00291 }
00292 
00293 // Test file
00294 bool DirectoryExists(const std::string& rDirectory) {
00295   DIR *thedir;
00296   thedir=opendir(rDirectory.c_str()); 
00297   if(thedir) closedir(thedir);
00298   return thedir!= 0;
00299 }
00300 
00301 // scan directory
00302 std::set< std::string > ReadDirectory(const std::string& rDirectory) {
00303   std::set< std::string >  res;
00304   DIR *thedir;
00305   struct dirent *theent;
00306   thedir=opendir(rDirectory.c_str()); 
00307   if(!thedir) return res;
00308   while((theent=readdir(thedir))) {
00309     std::string fname(theent->d_name);     
00310     if(fname==".") continue;
00311     if(fname=="..") continue;
00312     res.insert(fname);
00313   }
00314   return res;
00315 }
00316 
00317 // Test file
00318 bool FileExists(const std::string& rFilename) {
00319   std::fstream fp;
00320   fp.open(rFilename.c_str(), std::ios::in | std::ios::binary);
00321   return fp.good();
00322 }
00323 
00324 // Delete file
00325 bool FileDelete(const std::string& rFilename) {
00326   return remove(rFilename.c_str()) == 0;
00327 }
00328 
00329 // Copy file
00330 bool FileCopy(const std::string& rFromFile, const std::string& rToFile) {
00331   std::ifstream froms(rFromFile.c_str(), std::ios::binary);
00332   std::ofstream tos(rToFile.c_str(), std::ios::binary);
00333   tos << froms.rdbuf();
00334   tos.flush();
00335   return !(froms.fail() || tos.fail());
00336 }
00337 
00338 // ConsoleOut class
00339 // Note: console-out is not re-entrant; for multithreaded applications
00340 // you must derive a class that has built-in mutexes; 
00341 ConsoleOut::ConsoleOut(void) : pStream(NULL), mMute(false) {
00342   pInstance=this;
00343 }
00344 ConsoleOut::~ConsoleOut(void) {
00345   if(pStream) { pStream->flush(); delete pStream; }
00346   if(this==smpInstance) smpInstance=NULL;
00347 }
00348 ConsoleOut* ConsoleOut::G(void) {
00349   if(!smpInstance) smpInstance= new ConsoleOut();
00350   return smpInstance->pInstance;
00351 }
00352 void ConsoleOut::Redirect(ConsoleOut* out) {
00353   std::string fname = smpInstance->pInstance->Filename();
00354   smpInstance->pInstance->ToFile("");
00355   smpInstance->pInstance=out; 
00356   if(!smpInstance->pInstance) smpInstance->pInstance=smpInstance;
00357   smpInstance->pInstance->ToFile(fname);
00358 }
00359 void ConsoleOut::ToFile(const std::string& filename) {
00360   if(pStream) { pStream->flush(); delete pStream; }
00361   pStream=NULL;
00362   mFilename=filename;
00363   if(mFilename=="") return;
00364   pStream = new std::ofstream();
00365   pStream->open(mFilename.c_str(),std::ios::app);
00366 }
00367 void ConsoleOut::Write(const std::string& message,long int cntnow, long int cntdone) {
00368   if(mMute) return;
00369   DoWrite(message,cntnow,cntdone);
00370 }
00371 void ConsoleOut::DoWrite(const std::string& message,long int cntnow, long int cntdone) {
00372   (void) cntnow; (void) cntdone;
00373   std::ostream* sout=pStream;
00374   if(!sout) sout=&std::cerr;
00375   *sout << message;
00376   sout->flush();
00377 }
00378 
00379 // global instance
00380 ConsoleOut* ConsoleOut::smpInstance=NULL;
00381  
00382 
00383 
00384 // debugging: objectcount
00385 std::map<std::string,long int>* ObjectCount::mspMax=NULL;
00386 std::map<std::string,long int>* ObjectCount::mspCount=NULL;
00387 bool ObjectCount::msDone=false;
00388 ObjectCount::ObjectCount(void) {
00389   mspCount= new std::map<std::string,long int>();
00390   mspMax= new std::map<std::string,long int>();
00391   msDone=true; 
00392 }
00393 void  ObjectCount::Init(void) {
00394  if(!msDone) ObjectCount();
00395 }
00396 void  ObjectCount::Inc(const std::string& rTypeName) {
00397   if(!msDone) ObjectCount();
00398   long int cnt = ((*mspCount)[rTypeName]+=1);
00399   if((*mspMax)[rTypeName]<cnt) (*mspMax)[rTypeName]=cnt;
00400 }
00401 void  ObjectCount::Dec(const std::string& rTypeName) {
00402   if(!msDone) ObjectCount();
00403   (*mspCount)[rTypeName]-=1;
00404 }
00405 
00406 
00407 // debugging: report on exit function
00408 void ExitFunction(void){
00409 #ifdef FAUDES_DEBUG_CODE
00410   FAUDES_WRITE_CONSOLE("faudes::ExitFunction():");
00411   // be sure its up and running
00412   ObjectCount::Init();
00413   // get rid of all registry prototypes
00414   //TypeRegistry::G()->ClearAll();  
00415   //FunctionRegistry::G()->Clear();  
00416   // prepare report
00417   std::map<std::string,long int>::iterator cit;
00418   cit=ObjectCount::mspCount->begin();
00419   for(;cit!=ObjectCount::mspCount->end();cit++) {
00420     FAUDES_WRITE_CONSOLE( cit->first << ": #" << ToStringInteger(cit->second) <<
00421      " (max #" << (*ObjectCount::mspMax)[cit->first] << ")");
00422   }
00423 #endif
00424 }
00425  
00426 
00427 #ifdef FAUDES_DEBUG_CODE
00428 // report on exit install
00429 class ExitFunctionInstall {
00430 private:
00431   static bool mDone;
00432   static ExitFunctionInstall mInstance;
00433   ExitFunctionInstall(void) {
00434     if(mDone) return;
00435     FAUDES_WRITE_CONSOLE("ExitFunctionInstall()");
00436     std::atexit(ExitFunction);
00437     mDone=true;
00438   } 
00439 };
00440 // exit function: global data
00441 bool ExitFunctionInstall::mDone=false;
00442 ExitFunctionInstall ExitFunctionInstall::mInstance;
00443 #endif
00444 
00445 // test protocol: token writer and file
00446 TokenWriter* gTestProtocolTw=NULL;
00447 std::string  gTestProtocolFr;
00448 
00449 // test protocol: setup
00450 std::string TestProtocol(const std::string& rSource) {
00451   if(gTestProtocolTw) return gTestProtocolFr;
00452   // set up filename
00453   std::string filename=rSource;
00454   // fix empty source
00455   if(filename=="") filename="faudes_dump";
00456   // remove directory
00457   filename=ExtractFilename(filename);
00458   // remove extension
00459   std::string::size_type pos=0;
00460   for(;pos<filename.length();pos++) 
00461     if(filename.at(pos)=='.') filename.at(pos)='_';
00462   // append extension
00463   filename.append(".prot");
00464   // record nominal case
00465   gTestProtocolFr=filename;
00466   // prepend prefix
00467   filename.insert(0,"tmp_");
00468   // initialise token writer
00469   gTestProtocolTw= new TokenWriter(filename);
00470   // report filename
00471   return gTestProtocolFr;
00472 }
00473   
00474 // test protocol: dump
00475 void TestProtocol(const std::string& rMessage, const Type& rData, bool full) {
00476   if(!gTestProtocolTw) return;
00477   gTestProtocolTw->WriteComment("%%% test mark: " + rMessage);
00478   if(full) rData.Write(*gTestProtocolTw);
00479   else rData.SWrite(*gTestProtocolTw);
00480   gTestProtocolTw->WriteComment("");
00481   gTestProtocolTw->WriteComment("");
00482   gTestProtocolTw->WriteComment("");
00483   *gTestProtocolTw << "\n";
00484 }
00485 void TestProtocol(const std::string& rMessage, bool data) {
00486   Boolean fbool(data);
00487   TestProtocol(rMessage,fbool,true);
00488 } 
00489 void TestProtocol(const std::string& rMessage, long int data) {
00490   Integer fint(data);
00491   TestProtocol(rMessage,fint,true);
00492 } 
00493 void TestProtocol(const std::string& rMessage, const std::string& rData) {
00494  String fstr(rData);
00495  TestProtocol(rMessage,fstr,true);
00496 } 
00497 
00498 // test protocol: compare
00499 bool TestProtocol(void) {
00500   // bail out on no protocol
00501   if(!gTestProtocolTw) return true;
00502   // close protocol file
00503   std::string prot=gTestProtocolTw->FileName();
00504   delete gTestProtocolTw;
00505   gTestProtocolTw=NULL;
00506   // open protocol 
00507   std::fstream fp;
00508   fp.open(prot.c_str(), std::ios::in | std::ios::binary);
00509   if(!fp.good()) { 
00510     FAUDES_WRITE_CONSOLE("TestProtocol(): could not open protocol \"" << prot << "\"");
00511     return false;
00512   }
00513   // open reference
00514   std::string ref=gTestProtocolFr;
00515   std::fstream fr;
00516   fr.open(ref.c_str(), std::ios::in | std::ios::binary); 
00517   if(!fr.good()) { 
00518     ref="data"+faudes_pathsep()+ref;
00519     fr.clear(); // mingw's runtime will not clear on open
00520     fr.open(ref.c_str(), std::ios::in | std::ios::binary);
00521   }
00522   if(!fr.good()) { 
00523     FAUDES_WRITE_CONSOLE("TestProtocol(): could not open/find reference \"" << gTestProtocolFr << "\"");
00524     return true;
00525   }
00526   // perform comparision
00527   int dline=-1;
00528   int cline=1;    
00529   try{
00530     while(true) {
00531       // read next char
00532       char cp = fp.get();
00533       char cr= fr.get();
00534       // eof
00535       if(fp.eof() && fr.eof()) { break; }
00536       if(!fp.good() || !fr.good()) { dline=cline; break;}
00537       // cheap normalize cr/lf: ignore \r (assume no double \r
00538       if( cp=='\r' && cr =='\r') continue;
00539       if( cp=='\r' && fp.eof()){ dline=cline; break;}
00540       if( cp=='\r') cp = fp.get();      
00541       if( cr=='\r' && fr.eof()){ dline=cline; break;}
00542       if( cr=='\r') cr = fr.get();   
00543       // count lines
00544       if( cr=='\n') cline++;
00545       // sense mitmatch
00546       if( cp!= cr ){dline=cline; break;}
00547     }
00548   } catch(std::ios::failure&) {
00549     throw Exception("TestProtocol()", "io error at line " + ToStringInteger(cline), 1);
00550   }
00551   // done
00552   if(dline>=0) {
00553     FAUDES_WRITE_CONSOLE("TestProtocol(): using reference " << ref << "");
00554     FAUDES_WRITE_CONSOLE("TestProtocol(): found difference at line " << dline << "");
00555   }
00556   return dline== -1;
00557 }
00558 
00559 
00560 
00561 // declare loop callback
00562 static bool (*gBreakFnct)(void)=0;
00563 
00564 // set loop callback
00565 void LoopCallback( bool pBreak(void)) {
00566   gBreakFnct=pBreak;
00567 }
00568 
00569 // do loop callback
00570 // note: this function is meant to be "quiet" during normal
00571 // operation in order not to mess up console logging
00572 void LoopCallback(void){
00573   if(!gBreakFnct) return;
00574   if(! (*gBreakFnct)() ) return;
00575   throw Exception("LoopCallback", "break on application request", 110);
00576 }
00577 
00578 } // namespace faudes

libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen