libFAUDES
Sections
Index
|
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 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, Christian Wamser, 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.22s --- 2013.10.07 --- c++ source docu by doxygen