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