2 # ---------------------------------------------------------------------
4 # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image
6 # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton
7 # Previous Authors : Laurent Guigues, Jean-Pierre Roux
8 # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil
10 # This software is governed by the CeCILL-B license under French law and
11 # abiding by the rules of distribution of free software. You can use,
12 # modify and/ or redistribute the software under the terms of the CeCILL-B
13 # license as circulated by CEA, CNRS and INRIA at the following URL
14 # http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
15 # or in the file LICENSE.txt.
17 # As a counterpart to the access to the source code and rights to copy,
18 # modify and redistribute granted by the license, users are provided only
19 # with a limited warranty and the software's author, the holder of the
20 # economic rights, and the successive licensors have only limited
23 # The fact that you are presently reading this means that you have had
24 # knowledge of the CeCILL-B license and that you accept its terms.
25 # ------------------------------------------------------------------------ */
28 /*=========================================================================
30 Module: $RCSfile: bbtkUtilities.cxx,v $
32 Date: $Date: 2012/11/16 08:49:01 $
33 Version: $Revision: 1.15 $
34 =========================================================================*/
39 #include "bbtkUtilities.h"
40 #include "bbtkMessageManager.h"
47 #if defined(MACOSX) // assume this is OSX
48 # include <sys/param.h>
49 # include <mach-o/dyld.h> // _NSGetExecutablePath : must add -framework CoreFoundation to link line
52 # define PATH_MAX MAXPATHLEN
56 #ifndef PATH_MAX // If not defined yet : do it
57 # define PATH_MAX 2048
65 // ======================================================================
66 // See : http://www.techbytes.ca/techbyte103.html for more O.S.
67 bool Utilities::FileExists(std::string strFilename)
69 struct stat stFileInfo;
73 // Attempt to get the file attributes
74 intStat = stat(strFilename.c_str(),&stFileInfo);
77 // We were able to get the file attributes
78 // so the file obviously exists.
83 // We were not able to get the file attributes.
84 // This may mean that we don't have permission to
85 // access the folder which contains this file. If you
86 // need to do that level of checking, lookup the
87 // return values of stat which will give you
88 // more details on why stat failed.
96 // =====================================================================
98 std::string Utilities::ExtractPackageName(const std::string &name,
104 std::string::size_type slash_position = name.find_last_of("/\\");
105 if (slash_position != std::string::npos)
107 pkgname = name.substr(slash_position+1,std::string::npos);
108 path = name.substr(0,slash_position);
109 // std::cout << "F:P='"<<path<<"'"<<std::endl;//+1,std::string::npos);
116 // remove {.so | dll} if any
117 std::string::size_type dot_position = pkgname.find_last_of('.');
118 if (dot_position != std::string::npos){
119 pkgname = pkgname.substr(0,dot_position);
121 #if defined(__GNUC__)
124 // shared lib name = libbb<name>.so
126 // remove {libbb} if any
127 if (memcmp ( pkgname.c_str(), "libbb", 5) == 0) {
128 pkgname = pkgname.substr(5, pkgname.length());
131 /// \ \todo what would happen if (stupid) user names his package 'libbb' ?!?
132 /// \ --> Should be forbidden!
134 #elif defined(_WIN32)
137 // shared lib name = <name>.dll
139 // EED Problem loading package call bbtkTools
140 // // remove {bb} if any
141 if (memcmp (pkgname.c_str(), "bb", 2) == 0) {
142 pkgname = pkgname.substr(2, pkgname.length());
146 /// \ \todo what would happen if (stupid) user names his package 'bb' ?!?
147 /// \ --> Should be forbidden!
150 bbtkError("neither __GNUC__ nor _WIN32 ?!? How did you compile ?");
155 //=====================================================================
156 std::string Utilities::ExtractScriptName(const std::string &name,
161 std::string::size_type slash_position = name.find_last_of("/\\");
162 if (slash_position != std::string::npos) {
163 pkgname =name.substr(slash_position+1,std::string::npos);
164 path = name.substr(0,slash_position);
168 // remove {.bbs } if any
169 std::string::size_type dot_position = pkgname.find_last_of('.');
170 if (dot_position != std::string::npos){
171 pkgname = pkgname.substr(0,dot_position);
176 // ========================================================================
178 std::string Utilities::ExpandLibName(const std::string &name, bool verbose)
180 // ----- Think of expanding path name ( ./ ../ ../../ )
182 char buf[2048]; // for getcwd
183 char * currentDir = getcwd(buf, 2048);
184 std::string cwd(currentDir);
185 std::string libname(name);
186 std::string fileSeparator;
187 fileSeparator = ConfigurationFile::GetInstance().Get_file_separator();
188 // tooHigh : true is user supplies a library pathname with too many "../"
189 bool tooHigh = false;
191 //std::cout << "------------------cwd [" << cwd << "] name [" << name << "]" << std::endl;
193 if ( name[0] == '/' || name[1] == ':' ) // Linux or Windows absolute name
197 else if ( name =="." )
199 libname = cwd + fileSeparator;
202 else if (name[0] == '.' && (name[1] == '/' || name[1] == '\\') )
204 libname = cwd + fileSeparator + name.substr(2, name.length());
207 else if ( name[0] == '.' && name[1] == '.' /* && (name[2] == '/' || name[2] == '\\') */ )
209 if ( IsAtRoot(cwd) ) // hope it gets / (for Linux), C: D: (for Windows)
211 // if we are already at / or c: --> hopeless
213 std::cout << " File path [" << name << "] doesn't exist" << std::endl;
218 // iterate on ../ and go up from the current working dir!
220 bool alreadyProcessRoot = false;
222 //if (a[a.size()-1] != fileSeparator[0])
223 // a.append(fileSeparator);
224 //std::cout << "------------------a [" << a << "]" << std::endl;
226 for(;;) // wild loop !
228 std::string::size_type slash_position = cwd.find_last_of(fileSeparator);
229 if (slash_position != std::string::npos) {
230 if (slash_position == 0)
232 cwd = cwd.substr(0,slash_position/*+1*/);
233 //std::cout << "------------------cwd [" << cwd << "]" << std::endl;
239 a = a.substr(3, /*name.length()*/ a.length()); // remove ../
240 //std::cout << "------------------a [" << a << "]" << std::endl;
241 if (a == "" || alreadyProcessRoot)
244 std::cout << " File path : [" << name << "] doesn't exist" << std::endl;
248 // std::string b = cwd + a;
250 char c = cwd[cwd.size()-1];
251 if (c != '/' && c != '\\' )
252 libname += fileSeparator;
255 if ( a[0] != '.' ) // if . (probabely ../), loop again
259 alreadyProcessRoot = true;
261 } // end iterating on ../
263 //std::cout << "------------------out of loop]" << std::endl;
268 } // ----- End of expanding path name ( ./ ../ ../../ )
270 std::cout <<"* ERROR in ExpandLibName : should never get here!" << std::endl;
272 return(""); // Will never get here!
275 // ===================================================================================
277 std::string Utilities::MakeLibnameFromPath(std::string path, std::string pkgname)
279 std::string libname = path;
281 char c = path[path.size()-1];
282 #if defined(__GNUC__)
294 #elif defined(_WIN32)
307 // ===================================================================================
309 std::string Utilities::MakePkgnameFromPath(std::string path, std::string pkgname, bool addExt)
311 std::string libname = path;
313 char c = path[path.size()-1];
314 if (c != '/' && c != '\\')
316 libname += ConfigurationFile::GetInstance().Get_file_separator ();
321 int l = libname.size();
324 if (libname.substr(l-4, 4) != ".bbs")
326 libname = libname + ".bbs";
334 // =======================================================================
336 // =======================================================================
337 /// Returns the user settings dir, e.g. /home/username/.bbtk
338 std::string Utilities::GetUserSettingsDir()
340 std::string str_Home=Utilities::GetEnvHome();
341 std::string fullname = str_Home + "/.bbtk";
342 MakeValidFileName(fullname);
347 // =======================================================================
348 /// Builds the complete path to the file 'name' located
349 /// in user settings dir, e.g. /home/username/.bbtk/
350 std::string Utilities::MakeUserSettingsFullFileName(const std::string& name)
352 std::string str_home=Utilities::GetEnvHome();
353 std::string fullname = str_home + "/.bbtk/" + name;
354 MakeValidFileName(fullname);
357 // =======================================================================
360 // =======================================================================
361 void Utilities::CreateDirectoryIfNeeded( std::string const &dirName)
363 if (FileExists(dirName)) return;
364 std::string cmd("mkdir \"");
369 // =======================================================================
372 //========================================================================
373 bool Utilities::IsAtRoot(std::string cwd)
375 if ( cwd == "/" // hope it gets / (for Linux)
376 || (cwd.size() <= 3 && cwd[1] == ':') ) // hope it gets C: D: (for Windows)
381 // ======================================================================
383 // ======================================================================
384 bool Utilities::IsDirectory(std::string const &dirName)
388 if ( stat(dirName.c_str(), &fs) == 0 )
391 return ((fs.st_mode & _S_IFDIR) != 0);
393 return S_ISDIR(fs.st_mode);
401 // =======================================================================
403 // =======================================================================
404 void Utilities::SplitAroundFirstDot( const std::string& in,
408 std::string delimiter = ".";
409 std::string::size_type pos = in.find_first_of(delimiter);
410 if (std::string::npos != pos)
412 left = in.substr(0,pos);
413 right = in.substr(pos+1,in.size());
420 bbtkGlobalError("Token '"<<in<<"' : expected 'a.b' format but no dot found");
423 //=======================================================================
425 //=======================================================================
426 void Utilities::SplitString ( const std::string& str,
427 const std::string& delimiters,
428 std::vector<std::string>& tokens)
430 // Skip delimiters at beginning.
431 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
432 // Find first delimiter.
433 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
435 while (std::string::npos != pos || std::string::npos != lastPos)
437 // Found a token, add it to the vector.
438 tokens.push_back(str.substr(lastPos, pos - lastPos));
439 // Skip delimiters. Note the "not_of"
440 lastPos = str.find_first_not_of(delimiters, pos);
441 // Find next delimiter
442 pos = str.find_first_of(delimiters, lastPos);
446 //=======================================================================
449 // ======================================================================
450 std::string Utilities::get_file_name(const std::string& s)
452 std::string::size_type slash_position = s.find_last_of("/\\");
453 if (slash_position != std::string::npos)
455 return s.substr(slash_position+1,std::string::npos);
462 //=======================================================================
465 // ========================================================================
467 * \brief Explore a directory with possibility of recursion
468 * return number of files read
469 * @param dirpath directory to explore
470 * @param recursive whether we want recursion or not
472 int Utilities::Explore(std::string const &dirpath, bool recursive, std::vector<std::string> &Filenames)
474 int numberOfFiles = 0;
475 std::string fileName;
477 std::string dirName = dirpath;
480 WIN32_FIND_DATA fileData;
481 HANDLE hFile = FindFirstFile((dirName+"\\*").c_str(), &fileData);
483 for(BOOL b = (hFile != INVALID_HANDLE_VALUE); b;
484 b = FindNextFile(hFile, &fileData))
486 fileName = fileData.cFileName;
487 if ( fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
489 // Need to check for . and .. to avoid infinite loop
490 if ( fileName != "." && fileName != ".." && recursive )
492 numberOfFiles += Explore(dirName+ "\\"+fileName,recursive,Filenames);
497 Filenames.push_back(dirName+"\\"+fileName);
501 DWORD dwError = GetLastError();
502 if (hFile != INVALID_HANDLE_VALUE)
504 if (dwError != ERROR_NO_MORE_FILES)
507 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
508 FORMAT_MESSAGE_FROM_SYSTEM|
509 FORMAT_MESSAGE_IGNORE_INSERTS,
511 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
512 (LPTSTR) &lpMsgBuf,0,NULL);
514 // ErrorMacro("FindNextFile error. Error is " << (char *)lpMsgBuf
515 // <<" for the directory : "<<dirName);
521 // Real POSIX implementation: scandir is a BSD extension only, and doesn't
522 // work on debian for example
523 //std::cout <<"in Explor dirname[" << dirName << "]" << std::endl;
524 DIR* dir = opendir(dirName.c_str());
529 //std::cout <<"Open OK" << std::endl;
530 // According to POSIX, the dirent structure contains a field char d_name[]
531 // of unspecified size, with at most NAME_MAX characters preceeding the
532 // terminating null character. Use of other fields will harm the porta-
533 // bility of your programs.
537 for (d = readdir(dir); d; d = readdir(dir))
539 fileName = dirName + "/" + d->d_name;
540 //std::cout <<"in Explor filename[" << fileName << "]" << std::endl;
541 if( stat(fileName.c_str(), &buf) != 0 )
543 //ErrorMacro( strerror(errno) );
545 if ( S_ISREG(buf.st_mode) ) //is it a regular file?
547 Filenames.push_back( fileName );
550 else if ( S_ISDIR(buf.st_mode) ) //directory?
552 if ( d->d_name[0] != '.' && recursive ) //we also skip hidden files
554 numberOfFiles += Explore( fileName, recursive, Filenames);
559 //ErrorMacro( "Unexpected error" );
563 if( closedir(dir) != 0 )
565 // ErrorMacro( strerror(errno) );
569 return numberOfFiles;
572 //=======================================================================
575 //=======================================================================
576 // Replaces substrings "\\n" by a real carriage return "\n"
577 void Utilities::SubsBackslashN ( std::string& s )
579 std::string ss("\\n");
580 std::string::size_type pos = 0;
582 const char* cr = "\n";
583 while ( pos != std::string::npos )
585 s.replace(pos,2,cr,1);
586 pos = s.find(ss, pos-1);
589 //=======================================================================
592 //=======================================================================
594 bool Utilities::loosematch(std::string stdLine,std::string stdOptions)
597 std::vector<std::string> tokens;
598 SplitString ( stdOptions,"|", tokens);
599 int i,size=tokens.size();
600 for (i=0; i<size; i++)
603 if ( strcmpi(stdLine.c_str(),tokens[i].c_str())==0)
608 if ( strcasecmp(stdLine.c_str(),tokens[i].c_str())==0)
617 //=========================================================================
619 //=========================================================================
620 // From http://www.fltk.org/newsgroups.php?gfltk.general+v:22083
622 int get_app_path (char *pname, size_t pathsize)
626 /* Oddly, the readlink(2) man page says no NULL is appended. */
627 /* So you have to do it yourself, based on the return value: */
628 pathsize --; /* Preserve a space to add the trailing NULL */
629 long result = readlink("/proc/self/exe", pname, pathsize);
632 pname[result] = 0; /* add the #@!%ing NULL */
634 if ((access(pname, 0) == 0))
635 return 0; /* file exists, return OK */
636 /*else name doesn't seem to exist, return FAIL (falls
645 long result = GetModuleFileName(NULL, pname2, pathsize);
646 // int ret = wcstombs ( pname, pname2, sizeof(pname) );
647 // long result = GetModuleFileName(NULL, pname, pathsize);
650 /* fix up the dir slashes... */
651 int len = strlen(pname);
653 for (idx = 0; idx < len; idx++)
655 if (pname[idx] == '\\') pname[idx] = '/';
658 for (idx = len-1; idx >=0 ; idx--)
660 if (pname[idx] == '/')
667 if ((access(pname, 0) == 0))
668 return 0; /* file exists, return OK */
669 /*else name doesn't seem to exist, return FAIL (falls
675 char *p = getexecname();
678 /* According to the Sun manpages, getexecname will
679 "normally" return an */
680 /* absolute path - BUT might not... AND that IF it is not,
682 /* getcwd() will "usually" be the correct thing... Urgh!
685 /* check pathname is absolute (begins with a / ???) */
686 if (p[0] == '/') /* assume this means we have an
689 strncpy(pname, p, pathsize);
690 if ((access(pname, 0) == 0))
691 return 0; /* file exists, return OK */
693 else /* if not, prepend getcwd() then check if file
696 getcwd(pname, pathsize);
697 long result = strlen(pname);
698 strncat(pname, "/", (pathsize - result));
700 strncat(pname, p, (pathsize - result));
702 if ((access(pname, 0) == 0))
703 return 0; /* file exists, return OK */
704 /*else name doesn't seem to exist, return FAIL
710 #ifdef MACOSX /* assume this is OSX */
712 from http://www.hmug.org/man/3/NSModule.html
714 extern int _NSGetExecutablePath(char *buf, unsigned long
717 _NSGetExecutablePath copies the path of the executable
718 into the buffer and returns 0 if the path was successfully
719 copied in the provided buffer. If the buffer is not large
720 enough, -1 is returned and the expected buffer size is
721 copied in *bufsize. Note that _NSGetExecutablePath will
722 return "a path" to the executable not a "real path" to the
723 executable. That is the path may be a symbolic link and
724 not the real file. And with deep directories the total
725 bufsize needed could be more than MAXPATHLEN.
728 char *given_path = (char*)malloc(MAXPATHLEN * 2);
729 if (!given_path) return status;
731 uint32_t npathsize = MAXPATHLEN * 2;
732 long result = _NSGetExecutablePath(given_path, &npathsize);
734 { /* OK, we got something - now try and resolve the real path...
736 if (realpath(given_path, pname) != NULL)
738 if ((access(pname, 0) == 0))
739 status = 0; /* file exists, return OK */
746 printf("EED Utilities get_app_path END\n");
748 return -1; /* Path Lookup Failed */
750 //=========================================================================
754 //=========================================================================
755 std::string Utilities::GetExecutablePath()
757 printf("EED Utilities::GetExecutablePath Start\n");
759 printf("EED Utilities::GetExecutablePath 1 \n");
760 int err = get_app_path(name, PATH_MAX);
761 printf("EED Utilities::GetExecutablePath 2 \n");
764 printf("EED Utilities::GetExecutablePath 2.1 \n");
765 // bbtkGlobalError("Could not determine current executable path ?");
769 printf("EED Utilities bbtkGlobalError XX Start\n");
772 printf("EED Utilities bbtkGlobalError XX A.1\n");
773 std::ostringstream s;
774 printf("EED Utilities bbtkGlobalError XX A.2\n");
775 s << "Could not determine current executable path ?";
776 printf("EED Utilities bbtkGlobalError XX A.3\n");
777 std::ostringstream f;
778 printf("EED Utilities bbtkGlobalError XX A.4\n");
779 f << __FILE__ << " (l."<<__LINE__<<")";
780 printf("EED Utilities bbtkGlobalError XX A.5\n");
781 std::string aa=f.str();
782 printf("EED Utilities bbtkGlobalError XX A.6\n");
783 std::string bb=f.str();
784 printf("EED Utilities bbtkGlobalError XX A.7\n");
785 bbtk::Exception e( "global scope",
789 printf("EED Utilities bbtkGlobalError XX B\n");
792 printf("EED Utilities bbtkGlobalError XX End\n");
797 printf("EED Utilities::GetExecutablePath 2.2 \n");
800 // remove the exe name
802 printf("EED Utilities::GetExecutablePath 3 >%s<\n",name);
803 slash = strrchr(name, VALID_FILE_SEPARATOR_CHAR);
804 printf("EED Utilities::GetExecutablePath 4 \n");
809 printf("EED Utilities::GetExecutablePath END \n");
812 //=========================================================================
815 std::string Utilities::GetEnvHome()
817 #if defined(__GNUC__)
819 char *envHome=getenv("HOME");
824 strHome = "/var/www/testwtdbg/docroot";
826 #elif defined(_WIN32)
827 std::string strHome( getenv("USERPROFILE") );
837 //---------NodeTree---------------
839 NodeTreeC::NodeTreeC()
844 NodeTreeC::NodeTreeC(std::string _data)
849 NodeTreeC::~NodeTreeC()
853 void NodeTreeC::deleteTree()
856 std::cout<<"NodeTreeC::deleteTree 1"<<std::endl;
857 childs.erase(childs.begin(),childs.begin()+childs.size());
858 std::cout<<"NodeTreeC::deleteTree 2"<<std::endl;
861 void NodeTreeC::insertChild(std::string _data)
863 NodeTreeC temp = NodeTreeC(_data);
864 childs.push_back(temp);
865 //std::cout<<"NodeTreeC::insertChild"<<std::endl;
868 void NodeTreeC::treeTour(int lvl)
870 std::string space = "";
871 for (int j=0; j<lvl ; j++){
875 std::cout <<space<<"data: "<< data << " size: "<< childs.size() << std::endl;
876 for(int i = 0 ; i < childs.size(); i++)
878 childs[i].treeTour(lvl);
882 void NodeTreeC::setData(std::string _data)
885 //std::cout<<"NodeTreeC::setData"<<std::endl;