About
User Reference
C++ API
luafaudes
Developer
Links
libFAUDES online
libFAUDES

Sections

Index

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

libFAUDES 2.22k --- 2013.04.02 --- c++ source docu by doxygen