1 /*=========================================================================
4 Module: $RCSfile: bbtkUtilities.h,v $
6 Date: $Date: 2008/03/26 08:27:19 $
7 Version: $Revision: 1.14 $
9 Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10 l'Image). All rights reserved. See doc/license.txt or
11 http://www.creatis.insa-lyon.fr/Public/bbtk/License.html for details.
13 This software is distributed WITHOUT ANY WARRANTY; without even
14 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 PURPOSE. See the above copyright notices for more information.
17 =========================================================================*/
22 * \brief struct bbtk::Utilities : various usefull methods
26 * \class bbtk::Utilities
27 * \brief various usefull methods
30 #ifndef __bbtkUtilities_h_INCLUDED__
31 #define __bbtkUtilities_h_INCLUDED__
33 #include "bbtkConfigurationFile.h"
34 #include "bbtkSystem.h"
37 #ifdef CMAKE_HAVE_TERMIOS_H
39 #define BBTK_USE_TERMIOS_BASED_PROMPT
47 #include <sys/types.h>
50 #include <cctype> // std::toupper
51 //#include "bbtkMessageManager.h"
55 /// Holds various usefull methods
56 struct BBTK_EXPORT Utilities
59 // ======================================================================
60 // See : http://www.techbytes.ca/techbyte103.html for more O.S.
61 static inline bool FileExists(std::string strFilename)
63 struct stat stFileInfo;
67 // Attempt to get the file attributes
68 intStat = stat(strFilename.c_str(),&stFileInfo);
71 // We were able to get the file attributes
72 // so the file obviously exists.
77 // We were not able to get the file attributes.
78 // This may mean that we don't have permission to
79 // access the folder which contains this file. If you
80 // need to do that level of checking, lookup the
81 // return values of stat which will give you
82 // more details on why stat failed.
90 // =====================================================================
92 static std::string ExtractPackageName(const std::string &name,
98 std::string::size_type slash_position = name.find_last_of("/\\");
99 if (slash_position != std::string::npos)
101 pkgname = name.substr(slash_position+1,std::string::npos);
102 path = name.substr(0,slash_position);
103 // std::cout << "F:P='"<<path<<"'"<<std::endl;//+1,std::string::npos);
110 // remove {.so | dll} if any
111 std::string::size_type dot_position = pkgname.find_last_of('.');
112 if (dot_position != std::string::npos){
113 pkgname = pkgname.substr(0,dot_position);
115 #if defined(__GNUC__)
118 // shared lib name = libbb<name>.so
120 // remove {libbb} if any
121 if (memcmp ( pkgname.c_str(), "libbb", 5) == 0) {
122 pkgname = pkgname.substr(5, pkgname.length());
125 /// \ \todo what would happen if (stupid) user names his package 'libbb' ?!?
126 /// \ --> Should be forbidden!
128 #elif defined(_WIN32)
131 // shared lib name = <name>.dll
133 // EED Problem loading package call bbtkTools
134 // // remove {bb} if any
135 if (memcmp (pkgname.c_str(), "bb", 2) == 0) {
136 pkgname = pkgname.substr(2, pkgname.length());
140 /// \ \todo what would happen if (stupid) user names his package 'bb' ?!?
141 /// \ --> Should be forbidden!
144 bbtkError("neither __GNUC__ nor _WIN32 ?!? How did you compile ?");
149 //=====================================================================
150 static std::string ExtractScriptName(const std::string &name,
155 std::string::size_type slash_position = name.find_last_of("/\\");
156 if (slash_position != std::string::npos) {
157 pkgname =name.substr(slash_position+1,std::string::npos);
158 path = name.substr(0,slash_position);
162 // remove {.bbs } if any
163 std::string::size_type dot_position = pkgname.find_last_of('.');
164 if (dot_position != std::string::npos){
165 pkgname = pkgname.substr(0,dot_position);
170 // ========================================================================
172 static std::string ExpandLibName(const std::string &name, bool verbose)
174 // ----- Think of expanding path name ( ./ ../ ../../ )
176 char buf[2048]; // for getcwd
177 char * currentDir = getcwd(buf, 2048);
178 std::string cwd(currentDir);
179 std::string libname(name);
180 std::string fileSeparator;
181 fileSeparator = ConfigurationFile::GetInstance().Get_file_separator();
182 // tooHigh : true is user supplies a library pathname with too many "../"
183 bool tooHigh = false;
185 //std::cout << "------------------cwd [" << cwd << "] name [" << name << "]" << std::endl;
187 if ( name[0] == '/' || name[1] == ':' ) // Linux or Windows absolute name
191 else if ( name =="." )
193 libname = cwd + fileSeparator;
196 else if (name[0] == '.' && (name[1] == '/' || name[1] == '\\') )
198 libname = cwd + fileSeparator + name.substr(2, name.length());
201 else if ( name[0] == '.' && name[1] == '.' /* && (name[2] == '/' || name[2] == '\\') */ )
203 if ( IsAtRoot(cwd) ) // hope it gets / (for Linux), C: D: (for Windows)
205 // if we are already at / or c: --> hopeless
207 std::cout << " File path [" << name << "] doesn't exist" << std::endl;
212 // iterate on ../ and go up from the current working dir!
214 bool alreadyProcessRoot = false;
216 //if (a[a.size()-1] != fileSeparator[0])
217 // a.append(fileSeparator);
218 //std::cout << "------------------a [" << a << "]" << std::endl;
220 for(;;) // wild loop !
222 std::string::size_type slash_position = cwd.find_last_of(fileSeparator);
223 if (slash_position != std::string::npos) {
224 if (slash_position == 0)
226 cwd = cwd.substr(0,slash_position/*+1*/);
227 //std::cout << "------------------cwd [" << cwd << "]" << std::endl;
233 a = a.substr(3, /*name.length()*/ a.length()); // remove ../
234 //std::cout << "------------------a [" << a << "]" << std::endl;
235 if (a == "" || alreadyProcessRoot)
238 std::cout << " File path : [" << name << "] doesn't exist" << std::endl;
242 // std::string b = cwd + a;
244 char c = cwd[cwd.size()-1];
245 if (c != '/' && c != '\\' )
246 libname += fileSeparator;
249 if ( a[0] != '.' ) // if . (probabely ../), loop again
253 alreadyProcessRoot = true;
255 } // end iterating on ../
257 //std::cout << "------------------out of loop]" << std::endl;
262 } // ----- End of expanding path name ( ./ ../ ../../ )
264 std::cout <<"* ERROR in ExpandLibName : should never get here!" << std::endl;
266 return(""); // Will never get here!
269 // ===================================================================================
271 static std::string MakeLibnameFromPath(std::string path, std::string pkgname)
273 std::string libname = path;
274 char c = path[path.size()-1];
275 #if defined(__GNUC__)
283 #elif defined(_WIN32)
285 libname = path+"\\bb";
292 // ===================================================================================
294 static inline std::string MakePkgnameFromPath(std::string path, std::string pkgname, bool addExt)
296 std::string libname = path;
297 char c = path[path.size()-1];
298 if (c != '/' && c != '\\')
300 libname += ConfigurationFile::GetInstance().Get_file_separator ();
305 int l = libname.size();
308 if (libname.substr(l-4, 4) != ".bbs")
310 libname = libname + ".bbs";
317 //========================================================================
319 static inline bool IsAtRoot(std::string cwd)
321 if ( cwd == "/" // hope it gets / (for Linux)
322 || (cwd.size() <= 3 && cwd[1] == ':') ) // hope it gets C: D: (for Windows)
328 // ======================================================================
330 static bool IsDirectory(std::string const &dirName)
334 if ( stat(dirName.c_str(), &fs) == 0 )
337 return ((fs.st_mode & _S_IFDIR) != 0);
339 return S_ISDIR(fs.st_mode);
348 // ===================================================================================
350 static inline void SplitAroundFirstDot( const std::string& in,
354 std::string delimiter = ".";
355 std::string::size_type pos = in.find_first_of(delimiter);
356 if (std::string::npos != pos)
358 left = in.substr(0,pos);
359 right = in.substr(pos+1,in.size());
364 // bbtkError(in<<" : expected 'a.b' format but no dot found");
369 //=======================================================================
370 static inline void SplitString ( const std::string& str,
371 const std::string& delimiters,
372 std::vector<std::string>& tokens)
374 // Skip delimiters at beginning.
375 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
376 // Find first delimiter.
377 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
379 while (std::string::npos != pos || std::string::npos != lastPos)
381 // Found a token, add it to the vector.
382 tokens.push_back(str.substr(lastPos, pos - lastPos));
383 // Skip delimiters. Note the "not_of"
384 lastPos = str.find_first_not_of(delimiters, pos);
385 // Find next delimiter
386 pos = str.find_first_of(delimiters, lastPos);
390 //=======================================================================
393 // ===================================================================================
395 static inline std::string get_file_name(const std::string& s)
397 std::string::size_type slash_position = s.find_last_of("/\\");
398 if (slash_position != std::string::npos)
400 return s.substr(slash_position+1,std::string::npos);
408 // ===================================================================================
410 * \brief Explore a directory with possibility of recursion
411 * return number of files read
412 * @param dirpath directory to explore
413 * @param recursive whether we want recursion or not
415 static int Explore(std::string const &dirpath, bool recursive, std::vector<std::string> &Filenames)
417 int numberOfFiles = 0;
418 std::string fileName;
420 std::string dirName = dirpath;
423 WIN32_FIND_DATA fileData;
424 HANDLE hFile = FindFirstFile((dirName+"*").c_str(), &fileData);
426 for(BOOL b = (hFile != INVALID_HANDLE_VALUE); b;
427 b = FindNextFile(hFile, &fileData))
429 fileName = fileData.cFileName;
430 if ( fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
432 // Need to check for . and .. to avoid infinite loop
433 if ( fileName != "." && fileName != ".." && recursive )
435 numberOfFiles += Explore(dirName+ "\\"+fileName,recursive,Filenames);
440 Filenames.push_back(dirName+fileName);
444 DWORD dwError = GetLastError();
445 if (hFile != INVALID_HANDLE_VALUE)
447 if (dwError != ERROR_NO_MORE_FILES)
450 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
451 FORMAT_MESSAGE_FROM_SYSTEM|
452 FORMAT_MESSAGE_IGNORE_INSERTS,
454 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
455 (LPTSTR) &lpMsgBuf,0,NULL);
457 // ErrorMacro("FindNextFile error. Error is " << (char *)lpMsgBuf
458 // <<" for the directory : "<<dirName);
464 // Real POSIX implementation: scandir is a BSD extension only, and doesn't
465 // work on debian for example
466 //std::cout <<"in Explor dirname[" << dirName << "]" << std::endl;
467 DIR* dir = opendir(dirName.c_str());
472 //std::cout <<"Open OK" << std::endl;
473 // According to POSIX, the dirent structure contains a field char d_name[]
474 // of unspecified size, with at most NAME_MAX characters preceeding the
475 // terminating null character. Use of other fields will harm the porta-
476 // bility of your programs.
480 for (d = readdir(dir); d; d = readdir(dir))
482 fileName = dirName + "/" + d->d_name;
483 //std::cout <<"in Explor filename[" << fileName << "]" << std::endl;
484 if( stat(fileName.c_str(), &buf) != 0 )
486 //ErrorMacro( strerror(errno) );
488 if ( S_ISREG(buf.st_mode) ) //is it a regular file?
490 Filenames.push_back( fileName );
493 else if ( S_ISDIR(buf.st_mode) ) //directory?
495 if ( d->d_name[0] != '.' && recursive ) //we also skip hidden files
497 numberOfFiles += Explore( fileName, recursive, Filenames);
502 //ErrorMacro( "Unexpected error" );
506 if( closedir(dir) != 0 )
508 // ErrorMacro( strerror(errno) );
512 return numberOfFiles;
517 //=======================================================================
518 // Replaces substrings "\\n" by a real carriage return "\n"
519 static inline void SubsBackslashN ( std::string& s )
521 std::string ss("\\n");
522 std::string::size_type pos = 0;
525 while ( pos != std::string::npos )
527 s.replace(pos,2,cr,1);
528 pos = s.find(ss, pos-1);
531 //=======================================================================
534 //========================================================================
535 // Usefull functions for html generation
536 //========================================================================
538 static inline void replace( std::string& str,
539 const std::string& what,
540 const std::string& with )
542 std::string::size_type pos = str.find( what );
543 while ( pos != std::string::npos )
545 str.replace( pos, what.size(), with );
546 pos = str.find( what, pos+what.size()-1 );
549 //========================================================================
551 static inline void html_format(std::string& str)
553 replace( str, "&", "&" );
554 replace( str, "<", "<" );
555 replace( str, ">", ">" );
559 //========================================================================
560 // Usefull functions OPTIONS string
561 //========================================================================
564 static bool loosematch(std::string stdLine,std::string stdOptions);
574 #endif //#ifndef __bbtkUtilities_h_INCLUDED__