cfl_helper.cppGo 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 |