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

libFAUDES 2.20s --- 2011.10.12 --- c++ source docu by doxygen