1 /*=========================================================================
3 Module: $RCSfile: bbtkUtilities.cxx,v $
5 Date: $Date: 2008/10/17 08:18:14 $
6 Version: $Revision: 1.7 $
7 =========================================================================*/
9 /* ---------------------------------------------------------------------
11 * Copyright (c) CREATIS-LRMN (Centre de Recherche en Imagerie Medicale)
12 * Authors : Eduardo Davila, Laurent Guigues, Jean-Pierre Roux
14 * This software is governed by the CeCILL-B license under French law and
15 * abiding by the rules of distribution of free software. You can use,
16 * modify and/ or redistribute the software under the terms of the CeCILL-B
17 * license as circulated by CEA, CNRS and INRIA at the following URL
18 * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
19 * or in the file LICENSE.txt.
21 * As a counterpart to the access to the source code and rights to copy,
22 * modify and redistribute granted by the license, users are provided only
23 * with a limited warranty and the software's author, the holder of the
24 * economic rights, and the successive licensors have only limited
27 * The fact that you are presently reading this means that you have had
28 * knowledge of the CeCILL-B license and that you accept its terms.
29 * ------------------------------------------------------------------------ */
32 #include "bbtkUtilities.h"
41 // ======================================================================
42 // See : http://www.techbytes.ca/techbyte103.html for more O.S.
43 bool Utilities::FileExists(std::string strFilename)
45 struct stat stFileInfo;
49 // Attempt to get the file attributes
50 intStat = stat(strFilename.c_str(),&stFileInfo);
53 // We were able to get the file attributes
54 // so the file obviously exists.
59 // We were not able to get the file attributes.
60 // This may mean that we don't have permission to
61 // access the folder which contains this file. If you
62 // need to do that level of checking, lookup the
63 // return values of stat which will give you
64 // more details on why stat failed.
72 // =====================================================================
74 std::string Utilities::ExtractPackageName(const std::string &name,
80 std::string::size_type slash_position = name.find_last_of("/\\");
81 if (slash_position != std::string::npos)
83 pkgname = name.substr(slash_position+1,std::string::npos);
84 path = name.substr(0,slash_position);
85 // std::cout << "F:P='"<<path<<"'"<<std::endl;//+1,std::string::npos);
92 // remove {.so | dll} if any
93 std::string::size_type dot_position = pkgname.find_last_of('.');
94 if (dot_position != std::string::npos){
95 pkgname = pkgname.substr(0,dot_position);
100 // shared lib name = libbb<name>.so
102 // remove {libbb} if any
103 if (memcmp ( pkgname.c_str(), "libbb", 5) == 0) {
104 pkgname = pkgname.substr(5, pkgname.length());
107 /// \ \todo what would happen if (stupid) user names his package 'libbb' ?!?
108 /// \ --> Should be forbidden!
110 #elif defined(_WIN32)
113 // shared lib name = <name>.dll
115 // EED Problem loading package call bbtkTools
116 // // remove {bb} if any
117 if (memcmp (pkgname.c_str(), "bb", 2) == 0) {
118 pkgname = pkgname.substr(2, pkgname.length());
122 /// \ \todo what would happen if (stupid) user names his package 'bb' ?!?
123 /// \ --> Should be forbidden!
126 bbtkError("neither __GNUC__ nor _WIN32 ?!? How did you compile ?");
131 //=====================================================================
132 std::string Utilities::ExtractScriptName(const std::string &name,
137 std::string::size_type slash_position = name.find_last_of("/\\");
138 if (slash_position != std::string::npos) {
139 pkgname =name.substr(slash_position+1,std::string::npos);
140 path = name.substr(0,slash_position);
144 // remove {.bbs } if any
145 std::string::size_type dot_position = pkgname.find_last_of('.');
146 if (dot_position != std::string::npos){
147 pkgname = pkgname.substr(0,dot_position);
152 // ========================================================================
154 std::string Utilities::ExpandLibName(const std::string &name, bool verbose)
156 // ----- Think of expanding path name ( ./ ../ ../../ )
158 char buf[2048]; // for getcwd
159 char * currentDir = getcwd(buf, 2048);
160 std::string cwd(currentDir);
161 std::string libname(name);
162 std::string fileSeparator;
163 fileSeparator = ConfigurationFile::GetInstance().Get_file_separator();
164 // tooHigh : true is user supplies a library pathname with too many "../"
165 bool tooHigh = false;
167 //std::cout << "------------------cwd [" << cwd << "] name [" << name << "]" << std::endl;
169 if ( name[0] == '/' || name[1] == ':' ) // Linux or Windows absolute name
173 else if ( name =="." )
175 libname = cwd + fileSeparator;
178 else if (name[0] == '.' && (name[1] == '/' || name[1] == '\\') )
180 libname = cwd + fileSeparator + name.substr(2, name.length());
183 else if ( name[0] == '.' && name[1] == '.' /* && (name[2] == '/' || name[2] == '\\') */ )
185 if ( IsAtRoot(cwd) ) // hope it gets / (for Linux), C: D: (for Windows)
187 // if we are already at / or c: --> hopeless
189 std::cout << " File path [" << name << "] doesn't exist" << std::endl;
194 // iterate on ../ and go up from the current working dir!
196 bool alreadyProcessRoot = false;
198 //if (a[a.size()-1] != fileSeparator[0])
199 // a.append(fileSeparator);
200 //std::cout << "------------------a [" << a << "]" << std::endl;
202 for(;;) // wild loop !
204 std::string::size_type slash_position = cwd.find_last_of(fileSeparator);
205 if (slash_position != std::string::npos) {
206 if (slash_position == 0)
208 cwd = cwd.substr(0,slash_position/*+1*/);
209 //std::cout << "------------------cwd [" << cwd << "]" << std::endl;
215 a = a.substr(3, /*name.length()*/ a.length()); // remove ../
216 //std::cout << "------------------a [" << a << "]" << std::endl;
217 if (a == "" || alreadyProcessRoot)
220 std::cout << " File path : [" << name << "] doesn't exist" << std::endl;
224 // std::string b = cwd + a;
226 char c = cwd[cwd.size()-1];
227 if (c != '/' && c != '\\' )
228 libname += fileSeparator;
231 if ( a[0] != '.' ) // if . (probabely ../), loop again
235 alreadyProcessRoot = true;
237 } // end iterating on ../
239 //std::cout << "------------------out of loop]" << std::endl;
244 } // ----- End of expanding path name ( ./ ../ ../../ )
246 std::cout <<"* ERROR in ExpandLibName : should never get here!" << std::endl;
248 return(""); // Will never get here!
251 // ===================================================================================
253 std::string Utilities::MakeLibnameFromPath(std::string path, std::string pkgname)
255 std::string libname = path;
256 char c = path[path.size()-1];
257 #if defined(__GNUC__)
265 #elif defined(_WIN32)
267 libname = path+"\\bb";
274 // ===================================================================================
276 std::string Utilities::MakePkgnameFromPath(std::string path, std::string pkgname, bool addExt)
278 std::string libname = path;
279 char c = path[path.size()-1];
280 if (c != '/' && c != '\\')
282 libname += ConfigurationFile::GetInstance().Get_file_separator ();
287 int l = libname.size();
290 if (libname.substr(l-4, 4) != ".bbs")
292 libname = libname + ".bbs";
299 // =======================================================================
300 /// Builds the complete path to the file 'name' located
301 /// in user settings dir, e.g. /home/username/.bbtk/
302 std::string Utilities::MakeUserSettingsFullFileName(const std::string& name)
304 #if defined(__GNUC__)
305 std::string str_home(getenv("HOME"));
306 #elif defined(_WIN32)
307 std::string str_home(getenv("USERPROFILE"));
309 std::string fullname = str_home + "/.bbtk/" + name;
310 Utilities::replace( fullname,
311 INVALID_FILE_SEPARATOR ,
312 VALID_FILE_SEPARATOR);
318 //========================================================================
320 bool Utilities::IsAtRoot(std::string cwd)
322 if ( cwd == "/" // hope it gets / (for Linux)
323 || (cwd.size() <= 3 && cwd[1] == ':') ) // hope it gets C: D: (for Windows)
329 // ======================================================================
331 bool Utilities::IsDirectory(std::string const &dirName)
335 if ( stat(dirName.c_str(), &fs) == 0 )
338 return ((fs.st_mode & _S_IFDIR) != 0);
340 return S_ISDIR(fs.st_mode);
349 // ===================================================================================
351 void Utilities::SplitAroundFirstDot( const std::string& in,
355 std::string delimiter = ".";
356 std::string::size_type pos = in.find_first_of(delimiter);
357 if (std::string::npos != pos)
359 left = in.substr(0,pos);
360 right = in.substr(pos+1,in.size());
365 // bbtkError(in<<" : expected 'a.b' format but no dot found");
370 //=======================================================================
371 void Utilities::SplitString ( const std::string& str,
372 const std::string& delimiters,
373 std::vector<std::string>& tokens)
375 // Skip delimiters at beginning.
376 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
377 // Find first delimiter.
378 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
380 while (std::string::npos != pos || std::string::npos != lastPos)
382 // Found a token, add it to the vector.
383 tokens.push_back(str.substr(lastPos, pos - lastPos));
384 // Skip delimiters. Note the "not_of"
385 lastPos = str.find_first_not_of(delimiters, pos);
386 // Find next delimiter
387 pos = str.find_first_of(delimiters, lastPos);
391 //=======================================================================
394 // ===================================================================================
396 std::string Utilities::get_file_name(const std::string& s)
398 std::string::size_type slash_position = s.find_last_of("/\\");
399 if (slash_position != std::string::npos)
401 return s.substr(slash_position+1,std::string::npos);
409 // ===================================================================================
411 * \brief Explore a directory with possibility of recursion
412 * return number of files read
413 * @param dirpath directory to explore
414 * @param recursive whether we want recursion or not
416 int Utilities::Explore(std::string const &dirpath, bool recursive, std::vector<std::string> &Filenames)
418 int numberOfFiles = 0;
419 std::string fileName;
421 std::string dirName = dirpath;
424 WIN32_FIND_DATA fileData;
425 HANDLE hFile = FindFirstFile((dirName+"\\*").c_str(), &fileData);
427 for(BOOL b = (hFile != INVALID_HANDLE_VALUE); b;
428 b = FindNextFile(hFile, &fileData))
430 fileName = fileData.cFileName;
431 if ( fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
433 // Need to check for . and .. to avoid infinite loop
434 if ( fileName != "." && fileName != ".." && recursive )
436 numberOfFiles += Explore(dirName+ "\\"+fileName,recursive,Filenames);
441 Filenames.push_back(dirName+"\\"+fileName);
445 DWORD dwError = GetLastError();
446 if (hFile != INVALID_HANDLE_VALUE)
448 if (dwError != ERROR_NO_MORE_FILES)
451 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
452 FORMAT_MESSAGE_FROM_SYSTEM|
453 FORMAT_MESSAGE_IGNORE_INSERTS,
455 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
456 (LPTSTR) &lpMsgBuf,0,NULL);
458 // ErrorMacro("FindNextFile error. Error is " << (char *)lpMsgBuf
459 // <<" for the directory : "<<dirName);
465 // Real POSIX implementation: scandir is a BSD extension only, and doesn't
466 // work on debian for example
467 //std::cout <<"in Explor dirname[" << dirName << "]" << std::endl;
468 DIR* dir = opendir(dirName.c_str());
473 //std::cout <<"Open OK" << std::endl;
474 // According to POSIX, the dirent structure contains a field char d_name[]
475 // of unspecified size, with at most NAME_MAX characters preceeding the
476 // terminating null character. Use of other fields will harm the porta-
477 // bility of your programs.
481 for (d = readdir(dir); d; d = readdir(dir))
483 fileName = dirName + "/" + d->d_name;
484 //std::cout <<"in Explor filename[" << fileName << "]" << std::endl;
485 if( stat(fileName.c_str(), &buf) != 0 )
487 //ErrorMacro( strerror(errno) );
489 if ( S_ISREG(buf.st_mode) ) //is it a regular file?
491 Filenames.push_back( fileName );
494 else if ( S_ISDIR(buf.st_mode) ) //directory?
496 if ( d->d_name[0] != '.' && recursive ) //we also skip hidden files
498 numberOfFiles += Explore( fileName, recursive, Filenames);
503 //ErrorMacro( "Unexpected error" );
507 if( closedir(dir) != 0 )
509 // ErrorMacro( strerror(errno) );
513 return numberOfFiles;
518 //=======================================================================
519 // Replaces substrings "\\n" by a real carriage return "\n"
520 void Utilities::SubsBackslashN ( std::string& s )
522 std::string ss("\\n");
523 std::string::size_type pos = 0;
526 while ( pos != std::string::npos )
528 s.replace(pos,2,cr,1);
529 pos = s.find(ss, pos-1);
532 //=======================================================================
536 bool Utilities::loosematch(std::string stdLine,std::string stdOptions)
539 std::vector<std::string> tokens;
540 SplitString ( stdOptions,"|", tokens);
541 int i,size=tokens.size();
542 for (i=0; i<size; i++)
545 if ( strcmpi(stdLine.c_str(),tokens[i].c_str())==0)
550 if ( strcasecmp(stdLine.c_str(),tokens[i].c_str())==0)