]> Creatis software - bbtk.git/blob - kernel/src/bbtkUtilities.cxx
*** empty log message ***
[bbtk.git] / kernel / src / bbtkUtilities.cxx
1 /*=========================================================================                                                                               
2   Program:   bbtk
3   Module:    $RCSfile: bbtkUtilities.cxx,v $
4   Language:  C++
5   Date:      $Date: 2008/10/17 08:18:14 $
6   Version:   $Revision: 1.7 $
7 =========================================================================*/
8
9 /* ---------------------------------------------------------------------
10
11 * Copyright (c) CREATIS-LRMN (Centre de Recherche en Imagerie Medicale)
12 * Authors : Eduardo Davila, Laurent Guigues, Jean-Pierre Roux
13 *
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.
20 *
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
25 *  liability. 
26 *
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 * ------------------------------------------------------------------------ */                                                                         
30
31
32 #include "bbtkUtilities.h"
33
34  
35
36 namespace bbtk
37 {
38
39
40
41             // ======================================================================
42     // See : http://www.techbytes.ca/techbyte103.html for more O.S.
43     bool Utilities::FileExists(std::string strFilename) 
44     {
45       struct stat stFileInfo;
46      bool blnReturn;
47      int intStat;
48      
49      // Attempt to get the file attributes
50      intStat = stat(strFilename.c_str(),&stFileInfo);
51      if(intStat == 0) 
52        {
53          // We were able to get the file attributes
54          // so the file obviously exists.
55          blnReturn = true;
56        } 
57      else 
58        {
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.
65          blnReturn = false;
66        }
67      
68      return(blnReturn);
69     }
70     
71     
72     // =====================================================================
73     
74     std::string Utilities::ExtractPackageName(const std::string  &name, 
75                                           std::string& path)
76     {
77       std::string pkgname;
78       path = "";
79       
80       std::string::size_type slash_position = name.find_last_of("/\\");
81       if (slash_position != std::string::npos) 
82         {
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);
86         }
87       else 
88         {
89           pkgname = name;
90         }
91       
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);
96       }      
97 #if defined(__GNUC__)
98       
99       // GCC mechanism
100       // shared lib name = libbb<name>.so
101       
102       // remove {libbb} if any
103       if (memcmp ( pkgname.c_str(), "libbb", 5) == 0) {
104         pkgname =  pkgname.substr(5, pkgname.length());
105       }
106       /*
107      /// \ \todo     what would happen if (stupid) user names his package 'libbb' ?!?
108       /// \ --> Should be forbidden!
109       */
110 #elif defined(_WIN32)
111       
112       // WIN 32 mechanism
113       // shared lib name = <name>.dll
114       
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());  
119       }
120       
121       /*
122      /// \ \todo     what would happen if (stupid) user names his package 'bb' ?!?
123      /// \ --> Should be forbidden!
124      */
125 #else
126       bbtkError("neither __GNUC__ nor _WIN32 ?!? How did you compile ?");
127 #endif      
128       return pkgname;
129     }
130     
131     //=====================================================================
132     std::string Utilities::ExtractScriptName(const std::string &name,
133                                          std::string& path)
134     {
135       std::string pkgname;
136       
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);      
141       } else {
142         pkgname = name;
143       }
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);
148       }
149       return pkgname;
150     }
151     
152     // ========================================================================
153
154     std::string Utilities::ExpandLibName(const std::string &name, bool verbose)
155     {
156       // -----   Think of expanding path name ( ./ ../ ../../ )
157       
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;
166       
167       //std::cout << "------------------cwd ["  << cwd << "] name [" << name << "]" << std::endl;
168       
169       if ( name[0] == '/' ||  name[1] == ':' ) // Linux or Windows absolute name
170         {
171           return(libname);
172         }
173       else if  ( name =="." )
174         {
175           libname = cwd  + fileSeparator;
176           return(libname);
177         }
178       else if  (name[0] == '.' && (name[1] == '/' || name[1] == '\\') )
179         {
180           libname = cwd  + fileSeparator + name.substr(2, name.length());
181           return(libname);
182         }
183       else if ( name[0] == '.' &&  name[1] == '.' /*  && (name[2] == '/' || name[2] == '\\') */ ) 
184         {
185           if ( IsAtRoot(cwd) )  // hope it gets / (for Linux),  C: D: (for Windows)
186       {  
187      // if we are already at / or c: --> hopeless  
188          if (verbose)
189            std::cout << "   File path [" <<  name << "] doesn't exist" << std::endl;
190          tooHigh = true;
191       }
192       else
193       {
194          // iterate on ../ and go up from the current working dir!
195          std::string a(name); 
196          bool alreadyProcessRoot = false;
197
198           //if (a[a.size()-1] != fileSeparator[0])
199           //   a.append(fileSeparator);
200 //std::cout << "------------------a ["  << a << "]" << std::endl;
201
202          for(;;)  // wild loop !
203          {
204             std::string::size_type slash_position = cwd.find_last_of(fileSeparator);
205             if (slash_position != std::string::npos) {
206              if (slash_position == 0)
207                 slash_position = 1;
208               cwd = cwd.substr(0,slash_position/*+1*/);
209 //std::cout << "------------------cwd ["  << cwd << "]" << std::endl;
210             //  if (a == "..") {
211             //    a = "";
212             //    break;
213             //   }
214             //   else
215                  a = a.substr(3, /*name.length()*/ a.length());  // remove ../
216 //std::cout << "------------------a ["  << a << "]" << std::endl;  
217               if (a == "" || alreadyProcessRoot)
218               {
219                 if (verbose)
220                   std::cout << "   File path : [" <<  name << "] doesn't exist" << std::endl;
221                 tooHigh = true;
222                 break;
223               }
224              // std::string b = cwd + a;
225               libname =  cwd;
226               char c = cwd[cwd.size()-1];
227               if (c != '/' && c != '\\' )
228                 libname += fileSeparator;
229               libname += a;
230
231               if ( a[0] != '.' ) // if . (probabely ../), loop again
232                 break;
233
234               if (IsAtRoot(cwd))
235                 alreadyProcessRoot = true;
236             }
237          } // end iterating on ../
238       }
239 //std::cout << "------------------out of loop]" << std::endl;        
240       if (tooHigh)
241          libname="";
242       return (libname);
243
244     }  // -----   End of expanding path name   ( ./ ../ ../../ )
245
246     std::cout <<"* ERROR in ExpandLibName : should never get here!" << std::endl;
247     // To avoid warning
248     return(""); // Will never get here!
249   }
250
251 // ===================================================================================
252
253   std::string Utilities::MakeLibnameFromPath(std::string path, std::string pkgname)
254   {
255     std::string libname = path;
256     char c = path[path.size()-1];    
257 #if defined(__GNUC__)
258        if (c != '/')
259           libname += "/libbb";
260        else
261           libname += "libbb";
262        libname += pkgname;
263        libname += ".so";
264          
265 #elif defined(_WIN32)
266        if (c != '\\')
267           libname = path+"\\bb";
268        libname += pkgname;
269        libname += ".dll";
270 #endif
271     return libname;    
272   }
273
274 // ===================================================================================
275
276   std::string Utilities::MakePkgnameFromPath(std::string path, std::string pkgname, bool addExt)
277   {
278     std::string libname = path;
279     char c = path[path.size()-1];
280     if (c != '/' && c != '\\')
281     {
282        libname +=  ConfigurationFile::GetInstance().Get_file_separator ();
283     }
284     libname += pkgname;
285     if (addExt)
286     {
287        int l = libname.size();
288        if (l>4)
289        {
290           if (libname.substr(l-4, 4) != ".bbs")
291           {
292                libname = libname + ".bbs";
293           }
294        }
295     }
296     return libname;
297   }
298
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)
303   {
304 #if defined(__GNUC__)
305     std::string str_home(getenv("HOME"));
306 #elif defined(_WIN32)
307     std::string str_home(getenv("USERPROFILE"));
308 #endif
309     std::string fullname = str_home + "/.bbtk/" + name;
310     Utilities::replace( fullname, 
311                         INVALID_FILE_SEPARATOR , 
312                         VALID_FILE_SEPARATOR);
313     return fullname;
314   }
315   
316
317
318     //========================================================================
319     
320     bool Utilities::IsAtRoot(std::string cwd)
321     {
322       if ( cwd == "/"              // hope it gets /     (for Linux)
323            || (cwd.size() <= 3 && cwd[1] == ':') ) // hope it gets C: D: (for Windows)
324         return (true);
325       else
326         return(false);
327     }
328     
329     // ======================================================================
330     
331     bool Utilities::IsDirectory(std::string const &dirName)
332     {
333       struct stat fs;
334       
335       if ( stat(dirName.c_str(), &fs) == 0 )
336         {
337 #if _WIN32
338           return ((fs.st_mode & _S_IFDIR) != 0);
339 #else
340           return S_ISDIR(fs.st_mode);
341 #endif
342         }
343       else
344         {
345           return false;
346         }
347     }
348     
349     // ===================================================================================
350     
351     void Utilities::SplitAroundFirstDot( const std::string& in,
352                                             std::string& left,
353                                             std::string& right)
354     {
355       std::string delimiter = ".";
356       std::string::size_type pos = in.find_first_of(delimiter);
357       if (std::string::npos != pos) 
358         {
359           left = in.substr(0,pos);
360           right = in.substr(pos+1,in.size());
361           
362         }
363       else
364         {
365           // bbtkError(in<<" : expected 'a.b' format but no dot found");
366           left ="";
367           right = "";
368         }
369     }
370     //=======================================================================
371     void Utilities::SplitString ( const std::string& str, 
372                                      const std::string& delimiters, 
373                                      std::vector<std::string>& tokens)
374     {
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);
379       
380       while (std::string::npos != pos || std::string::npos != lastPos)
381         {
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);
388         }
389       
390     }
391     //=======================================================================
392     
393     
394     // ===================================================================================
395     
396     std::string Utilities::get_file_name(const std::string& s) 
397     { 
398       std::string::size_type slash_position = s.find_last_of("/\\");
399       if (slash_position != std::string::npos) 
400         {
401           return  s.substr(slash_position+1,std::string::npos);   
402         }
403       else 
404         {
405           return s;
406         }
407     }
408     
409     // ===================================================================================
410     /**
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
415      */
416     int Utilities::Explore(std::string const &dirpath, bool recursive, std::vector<std::string> &Filenames)
417     {
418       int numberOfFiles = 0;
419       std::string fileName;
420       
421       std::string dirName = dirpath;
422       
423 #ifdef _MSC_VER
424       WIN32_FIND_DATA fileData;
425    HANDLE hFile = FindFirstFile((dirName+"\\*").c_str(), &fileData);
426
427    for(BOOL b = (hFile != INVALID_HANDLE_VALUE); b;
428        b = FindNextFile(hFile, &fileData))
429    {
430       fileName = fileData.cFileName;
431       if ( fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
432       {
433          // Need to check for . and .. to avoid infinite loop
434          if ( fileName != "." && fileName != ".." && recursive )
435          {
436             numberOfFiles += Explore(dirName+ "\\"+fileName,recursive,Filenames);
437          }
438       }
439       else
440       {
441          Filenames.push_back(dirName+"\\"+fileName);
442          numberOfFiles++;
443       }
444    }
445    DWORD dwError = GetLastError();
446    if (hFile != INVALID_HANDLE_VALUE) 
447       FindClose(hFile);
448    if (dwError != ERROR_NO_MORE_FILES) 
449    {
450       LPVOID lpMsgBuf;
451       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
452                     FORMAT_MESSAGE_FROM_SYSTEM|
453                     FORMAT_MESSAGE_IGNORE_INSERTS,
454                     NULL,GetLastError(),
455                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
456                     (LPTSTR) &lpMsgBuf,0,NULL);
457
458      // ErrorMacro("FindNextFile error. Error is " << (char *)lpMsgBuf
459      //             <<" for the directory : "<<dirName);
460       
461       return 0;
462    }
463
464 #else
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());
469    if (!dir)
470    {
471       return 0;
472    }
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.
478
479    struct stat buf;
480    dirent *d;
481    for (d = readdir(dir); d; d = readdir(dir))
482    {
483       fileName = dirName + "/" + d->d_name;
484 //std::cout <<"in Explor filename[" << fileName << "]" << std::endl;      
485       if( stat(fileName.c_str(), &buf) != 0 )
486       {
487          //ErrorMacro( strerror(errno) );
488       }
489       if ( S_ISREG(buf.st_mode) )    //is it a regular file?
490       {
491          Filenames.push_back( fileName );
492          numberOfFiles++;
493       }
494       else if ( S_ISDIR(buf.st_mode) ) //directory?
495       {
496          if ( d->d_name[0] != '.' && recursive ) //we also skip hidden files
497          {
498             numberOfFiles += Explore( fileName, recursive, Filenames);
499          }
500       }
501       else
502       {
503          //ErrorMacro( "Unexpected error" );
504          return -1;
505       }
506    }
507    if( closedir(dir) != 0 )
508    {
509      // ErrorMacro( strerror(errno) );
510    }
511 #endif
512
513   return numberOfFiles;
514
515 }
516
517
518     //=======================================================================
519     // Replaces substrings "\\n" by a real carriage return "\n"
520     void Utilities::SubsBackslashN ( std::string& s )
521     {
522       std::string ss("\\n");
523       std::string::size_type pos = 0;
524       pos = s.find(ss,0);
525       char* cr = "\n";
526       while ( pos != std::string::npos )
527         {
528           s.replace(pos,2,cr,1);
529           pos = s.find(ss, pos-1);
530         }
531     }
532     //=======================================================================
533
534
535
536 bool Utilities::loosematch(std::string stdLine,std::string stdOptions) 
537 {
538         bool result=false;
539           std::vector<std::string> tokens;
540           SplitString ( stdOptions,"|", tokens);
541           int i,size=tokens.size();  
542           for (i=0; i<size; i++)
543           {               
544 #ifdef WIN32
545                   if ( strcmpi(stdLine.c_str(),tokens[i].c_str())==0) 
546                   { 
547                           result=true; 
548                   }               
549 #else
550                   if ( strcasecmp(stdLine.c_str(),tokens[i].c_str())==0) 
551                   { 
552                           result=true; 
553                   }               
554 #endif
555
556           }
557           return result;
558 }
559
560
561
562 }