]> Creatis software - bbtk.git/blob - kernel/src/bbtkUtilities.cxx
0e57b2f904ef5ec7fac4170c096ab320580d01ed
[bbtk.git] / kernel / src / bbtkUtilities.cxx
1 #include "bbtkUtilities.h"
2
3  
4
5 namespace bbtk
6 {
7
8
9
10             // ======================================================================
11     // See : http://www.techbytes.ca/techbyte103.html for more O.S.
12     bool Utilities::FileExists(std::string strFilename) 
13     {
14       struct stat stFileInfo;
15      bool blnReturn;
16      int intStat;
17      
18      // Attempt to get the file attributes
19      intStat = stat(strFilename.c_str(),&stFileInfo);
20      if(intStat == 0) 
21        {
22          // We were able to get the file attributes
23          // so the file obviously exists.
24          blnReturn = true;
25        } 
26      else 
27        {
28          // We were not able to get the file attributes.
29          // This may mean that we don't have permission to
30          // access the folder which contains this file. If you
31          // need to do that level of checking, lookup the
32          // return values of stat which will give you
33          // more details on why stat failed.
34          blnReturn = false;
35        }
36      
37      return(blnReturn);
38     }
39     
40     
41     // =====================================================================
42     
43     std::string Utilities::ExtractPackageName(const std::string  &name, 
44                                           std::string& path)
45     {
46       std::string pkgname;
47       path = "";
48       
49       std::string::size_type slash_position = name.find_last_of("/\\");
50       if (slash_position != std::string::npos) 
51         {
52           pkgname = name.substr(slash_position+1,std::string::npos);
53           path = name.substr(0,slash_position);
54           //    std::cout << "F:P='"<<path<<"'"<<std::endl;//+1,std::string::npos);
55         }
56       else 
57         {
58           pkgname = name;
59         }
60       
61       // remove {.so | dll} if any
62       std::string::size_type dot_position = pkgname.find_last_of('.');      
63       if (dot_position != std::string::npos){
64         pkgname = pkgname.substr(0,dot_position);
65       }      
66 #if defined(__GNUC__)
67       
68       // GCC mechanism
69       // shared lib name = libbb<name>.so
70       
71       // remove {libbb} if any
72       if (memcmp ( pkgname.c_str(), "libbb", 5) == 0) {
73         pkgname =  pkgname.substr(5, pkgname.length());
74       }
75       /*
76      /// \ \todo     what would happen if (stupid) user names his package 'libbb' ?!?
77       /// \ --> Should be forbidden!
78       */
79 #elif defined(_WIN32)
80       
81       // WIN 32 mechanism
82       // shared lib name = <name>.dll
83       
84       // EED Problem loading package call bbtkTools
85       //     // remove {bb} if any
86       if (memcmp (pkgname.c_str(), "bb", 2) == 0) {
87         pkgname =  pkgname.substr(2, pkgname.length());  
88       }
89       
90       /*
91      /// \ \todo     what would happen if (stupid) user names his package 'bb' ?!?
92      /// \ --> Should be forbidden!
93      */
94 #else
95       bbtkError("neither __GNUC__ nor _WIN32 ?!? How did you compile ?");
96 #endif      
97       return pkgname;
98     }
99     
100     //=====================================================================
101     std::string Utilities::ExtractScriptName(const std::string &name,
102                                          std::string& path)
103     {
104       std::string pkgname;
105       
106       std::string::size_type slash_position = name.find_last_of("/\\");
107       if (slash_position != std::string::npos) {
108         pkgname =name.substr(slash_position+1,std::string::npos);
109         path = name.substr(0,slash_position);      
110       } else {
111         pkgname = name;
112       }
113       // remove {.bbs } if any
114       std::string::size_type dot_position = pkgname.find_last_of('.');
115       if (dot_position != std::string::npos){
116         pkgname = pkgname.substr(0,dot_position);
117       }
118       return pkgname;
119     }
120     
121     // ========================================================================
122
123     std::string Utilities::ExpandLibName(const std::string &name, bool verbose)
124     {
125       // -----   Think of expanding path name ( ./ ../ ../../ )
126       
127       char buf[2048]; // for getcwd
128       char * currentDir = getcwd(buf, 2048);
129       std::string cwd(currentDir);
130       std::string libname(name);
131       std::string fileSeparator;
132       fileSeparator = ConfigurationFile::GetInstance().Get_file_separator();
133       // tooHigh : true is user supplies a library pathname with too many "../"
134       bool tooHigh = false;
135       
136       //std::cout << "------------------cwd ["  << cwd << "] name [" << name << "]" << std::endl;
137       
138       if ( name[0] == '/' ||  name[1] == ':' ) // Linux or Windows absolute name
139         {
140           return(libname);
141         }
142       else if  ( name =="." )
143         {
144           libname = cwd  + fileSeparator;
145           return(libname);
146         }
147       else if  (name[0] == '.' && (name[1] == '/' || name[1] == '\\') )
148         {
149           libname = cwd  + fileSeparator + name.substr(2, name.length());
150           return(libname);
151         }
152       else if ( name[0] == '.' &&  name[1] == '.' /*  && (name[2] == '/' || name[2] == '\\') */ ) 
153         {
154           if ( IsAtRoot(cwd) )  // hope it gets / (for Linux),  C: D: (for Windows)
155       {  
156      // if we are already at / or c: --> hopeless  
157          if (verbose)
158            std::cout << "   File path [" <<  name << "] doesn't exist" << std::endl;
159          tooHigh = true;
160       }
161       else
162       {
163          // iterate on ../ and go up from the current working dir!
164          std::string a(name); 
165          bool alreadyProcessRoot = false;
166
167           //if (a[a.size()-1] != fileSeparator[0])
168           //   a.append(fileSeparator);
169 //std::cout << "------------------a ["  << a << "]" << std::endl;
170
171          for(;;)  // wild loop !
172          {
173             std::string::size_type slash_position = cwd.find_last_of(fileSeparator);
174             if (slash_position != std::string::npos) {
175              if (slash_position == 0)
176                 slash_position = 1;
177               cwd = cwd.substr(0,slash_position/*+1*/);
178 //std::cout << "------------------cwd ["  << cwd << "]" << std::endl;
179             //  if (a == "..") {
180             //    a = "";
181             //    break;
182             //   }
183             //   else
184                  a = a.substr(3, /*name.length()*/ a.length());  // remove ../
185 //std::cout << "------------------a ["  << a << "]" << std::endl;  
186               if (a == "" || alreadyProcessRoot)
187               {
188                 if (verbose)
189                   std::cout << "   File path : [" <<  name << "] doesn't exist" << std::endl;
190                 tooHigh = true;
191                 break;
192               }
193              // std::string b = cwd + a;
194               libname =  cwd;
195               char c = cwd[cwd.size()-1];
196               if (c != '/' && c != '\\' )
197                 libname += fileSeparator;
198               libname += a;
199
200               if ( a[0] != '.' ) // if . (probabely ../), loop again
201                 break;
202
203               if (IsAtRoot(cwd))
204                 alreadyProcessRoot = true;
205             }
206          } // end iterating on ../
207       }
208 //std::cout << "------------------out of loop]" << std::endl;        
209       if (tooHigh)
210          libname="";
211       return (libname);
212
213     }  // -----   End of expanding path name   ( ./ ../ ../../ )
214
215     std::cout <<"* ERROR in ExpandLibName : should never get here!" << std::endl;
216     // To avoid warning
217     return(""); // Will never get here!
218   }
219
220 // ===================================================================================
221
222   std::string Utilities::MakeLibnameFromPath(std::string path, std::string pkgname)
223   {
224     std::string libname = path;
225     char c = path[path.size()-1];    
226 #if defined(__GNUC__)
227        if (c != '/')
228           libname += "/libbb";
229        else
230           libname += "libbb";
231        libname += pkgname;
232        libname += ".so";
233          
234 #elif defined(_WIN32)
235        if (c != '\\')
236           libname = path+"\\bb";
237        libname += pkgname;
238        libname += ".dll";
239 #endif
240     return libname;    
241   }
242
243 // ===================================================================================
244
245   std::string Utilities::MakePkgnameFromPath(std::string path, std::string pkgname, bool addExt)
246   {
247     std::string libname = path;
248     char c = path[path.size()-1];
249     if (c != '/' && c != '\\')
250     {
251        libname +=  ConfigurationFile::GetInstance().Get_file_separator ();
252     }
253     libname += pkgname;
254     if (addExt)
255     {
256        int l = libname.size();
257        if (l>4)
258        {
259           if (libname.substr(l-4, 4) != ".bbs")
260           {
261                libname = libname + ".bbs";
262           }
263        }
264     }
265     return libname;
266   }
267
268   // =======================================================================
269   /// Builds the complete path to the file 'name' located 
270   /// in user settings dir, e.g. /home/username/.bbtk/
271   std::string Utilities::MakeUserSettingsFullFileName(const std::string& name)
272   {
273 #if defined(__GNUC__)
274     std::string str_home(getenv("HOME"));
275 #elif defined(_WIN32)
276     std::string str_home(getenv("USERPROFILE"));
277 #endif
278     std::string fullname = str_home + "/.bbtk/" + name;
279     Utilities::replace( fullname, 
280                         INVALID_FILE_SEPARATOR , 
281                         VALID_FILE_SEPARATOR);
282     return fullname;
283   }
284   
285
286
287     //========================================================================
288     
289     bool Utilities::IsAtRoot(std::string cwd)
290     {
291       if ( cwd == "/"              // hope it gets /     (for Linux)
292            || (cwd.size() <= 3 && cwd[1] == ':') ) // hope it gets C: D: (for Windows)
293         return (true);
294       else
295         return(false);
296     }
297     
298     // ======================================================================
299     
300     bool Utilities::IsDirectory(std::string const &dirName)
301     {
302       struct stat fs;
303       
304       if ( stat(dirName.c_str(), &fs) == 0 )
305         {
306 #if _WIN32
307           return ((fs.st_mode & _S_IFDIR) != 0);
308 #else
309           return S_ISDIR(fs.st_mode);
310 #endif
311         }
312       else
313         {
314           return false;
315         }
316     }
317     
318     // ===================================================================================
319     
320     void Utilities::SplitAroundFirstDot( const std::string& in,
321                                             std::string& left,
322                                             std::string& right)
323     {
324       std::string delimiter = ".";
325       std::string::size_type pos = in.find_first_of(delimiter);
326       if (std::string::npos != pos) 
327         {
328           left = in.substr(0,pos);
329           right = in.substr(pos+1,in.size());
330           
331         }
332       else
333         {
334           // bbtkError(in<<" : expected 'a.b' format but no dot found");
335           left ="";
336           right = "";
337         }
338     }
339     //=======================================================================
340     void Utilities::SplitString ( const std::string& str, 
341                                      const std::string& delimiters, 
342                                      std::vector<std::string>& tokens)
343     {
344       // Skip delimiters at beginning.
345       std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
346       // Find first delimiter.
347       std::string::size_type pos     = str.find_first_of(delimiters, lastPos);
348       
349       while (std::string::npos != pos || std::string::npos != lastPos)
350         {
351           // Found a token, add it to the vector.
352           tokens.push_back(str.substr(lastPos, pos - lastPos));
353           // Skip delimiters.  Note the "not_of"
354           lastPos = str.find_first_not_of(delimiters, pos);
355           // Find next delimiter
356           pos = str.find_first_of(delimiters, lastPos);
357         }
358       
359     }
360     //=======================================================================
361     
362     
363     // ===================================================================================
364     
365     std::string Utilities::get_file_name(const std::string& s) 
366     { 
367       std::string::size_type slash_position = s.find_last_of("/\\");
368       if (slash_position != std::string::npos) 
369         {
370           return  s.substr(slash_position+1,std::string::npos);   
371         }
372       else 
373         {
374           return s;
375         }
376     }
377     
378     // ===================================================================================
379     /**
380      * \brief   Explore a directory with possibility of recursion
381      *          return number of files read
382      * @param  dirpath   directory to explore
383      * @param  recursive whether we want recursion or not
384      */
385     int Utilities::Explore(std::string const &dirpath, bool recursive, std::vector<std::string> &Filenames)
386     {
387       int numberOfFiles = 0;
388       std::string fileName;
389       
390       std::string dirName = dirpath;
391       
392 #ifdef _MSC_VER
393       WIN32_FIND_DATA fileData;
394    HANDLE hFile = FindFirstFile((dirName+"\\*").c_str(), &fileData);
395
396    for(BOOL b = (hFile != INVALID_HANDLE_VALUE); b;
397        b = FindNextFile(hFile, &fileData))
398    {
399       fileName = fileData.cFileName;
400       if ( fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
401       {
402          // Need to check for . and .. to avoid infinite loop
403          if ( fileName != "." && fileName != ".." && recursive )
404          {
405             numberOfFiles += Explore(dirName+ "\\"+fileName,recursive,Filenames);
406          }
407       }
408       else
409       {
410          Filenames.push_back(dirName+"\\"+fileName);
411          numberOfFiles++;
412       }
413    }
414    DWORD dwError = GetLastError();
415    if (hFile != INVALID_HANDLE_VALUE) 
416       FindClose(hFile);
417    if (dwError != ERROR_NO_MORE_FILES) 
418    {
419       LPVOID lpMsgBuf;
420       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
421                     FORMAT_MESSAGE_FROM_SYSTEM|
422                     FORMAT_MESSAGE_IGNORE_INSERTS,
423                     NULL,GetLastError(),
424                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
425                     (LPTSTR) &lpMsgBuf,0,NULL);
426
427      // ErrorMacro("FindNextFile error. Error is " << (char *)lpMsgBuf
428      //             <<" for the directory : "<<dirName);
429       
430       return 0;
431    }
432
433 #else
434   // Real POSIX implementation: scandir is a BSD extension only, and doesn't 
435   // work on debian for example
436 //std::cout <<"in Explor dirname[" << dirName << "]" << std::endl; 
437    DIR* dir = opendir(dirName.c_str());
438    if (!dir)
439    {
440       return 0;
441    }
442 //std::cout <<"Open OK" << std::endl; 
443    // According to POSIX, the dirent structure contains a field char d_name[]
444    // of unspecified size, with at most NAME_MAX characters preceeding the
445    // terminating null character. Use of other fields will harm the  porta-
446    // bility of your programs.
447
448    struct stat buf;
449    dirent *d;
450    for (d = readdir(dir); d; d = readdir(dir))
451    {
452       fileName = dirName + "/" + d->d_name;
453 //std::cout <<"in Explor filename[" << fileName << "]" << std::endl;      
454       if( stat(fileName.c_str(), &buf) != 0 )
455       {
456          //ErrorMacro( strerror(errno) );
457       }
458       if ( S_ISREG(buf.st_mode) )    //is it a regular file?
459       {
460          Filenames.push_back( fileName );
461          numberOfFiles++;
462       }
463       else if ( S_ISDIR(buf.st_mode) ) //directory?
464       {
465          if ( d->d_name[0] != '.' && recursive ) //we also skip hidden files
466          {
467             numberOfFiles += Explore( fileName, recursive, Filenames);
468          }
469       }
470       else
471       {
472          //ErrorMacro( "Unexpected error" );
473          return -1;
474       }
475    }
476    if( closedir(dir) != 0 )
477    {
478      // ErrorMacro( strerror(errno) );
479    }
480 #endif
481
482   return numberOfFiles;
483
484 }
485
486
487     //=======================================================================
488     // Replaces substrings "\\n" by a real carriage return "\n"
489     void Utilities::SubsBackslashN ( std::string& s )
490     {
491       std::string ss("\\n");
492       std::string::size_type pos = 0;
493       pos = s.find(ss,0);
494       char* cr = "\n";
495       while ( pos != std::string::npos )
496         {
497           s.replace(pos,2,cr,1);
498           pos = s.find(ss, pos-1);
499         }
500     }
501     //=======================================================================
502
503
504
505 bool Utilities::loosematch(std::string stdLine,std::string stdOptions) 
506 {
507         bool result=false;
508           std::vector<std::string> tokens;
509           SplitString ( stdOptions,"|", tokens);
510           int i,size=tokens.size();  
511           for (i=0; i<size; i++)
512           {               
513 #ifdef WIN32
514                   if ( strcmpi(stdLine.c_str(),tokens[i].c_str())==0) 
515                   { 
516                           result=true; 
517                   }               
518 #else
519                   if ( strcasecmp(stdLine.c_str(),tokens[i].c_str())==0) 
520                   { 
521                           result=true; 
522                   }               
523 #endif
524
525           }
526           return result;
527 }
528
529
530
531 }