1 #include "bbtkUtilities.h"
10 // ======================================================================
11 // See : http://www.techbytes.ca/techbyte103.html for more O.S.
12 bool Utilities::FileExists(std::string strFilename)
14 struct stat stFileInfo;
18 // Attempt to get the file attributes
19 intStat = stat(strFilename.c_str(),&stFileInfo);
22 // We were able to get the file attributes
23 // so the file obviously exists.
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.
41 // =====================================================================
43 std::string Utilities::ExtractPackageName(const std::string &name,
49 std::string::size_type slash_position = name.find_last_of("/\\");
50 if (slash_position != std::string::npos)
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);
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);
69 // shared lib name = libbb<name>.so
71 // remove {libbb} if any
72 if (memcmp ( pkgname.c_str(), "libbb", 5) == 0) {
73 pkgname = pkgname.substr(5, pkgname.length());
76 /// \ \todo what would happen if (stupid) user names his package 'libbb' ?!?
77 /// \ --> Should be forbidden!
82 // shared lib name = <name>.dll
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());
91 /// \ \todo what would happen if (stupid) user names his package 'bb' ?!?
92 /// \ --> Should be forbidden!
95 bbtkError("neither __GNUC__ nor _WIN32 ?!? How did you compile ?");
100 //=====================================================================
101 std::string Utilities::ExtractScriptName(const std::string &name,
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);
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);
121 // ========================================================================
123 std::string Utilities::ExpandLibName(const std::string &name, bool verbose)
125 // ----- Think of expanding path name ( ./ ../ ../../ )
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;
136 //std::cout << "------------------cwd [" << cwd << "] name [" << name << "]" << std::endl;
138 if ( name[0] == '/' || name[1] == ':' ) // Linux or Windows absolute name
142 else if ( name =="." )
144 libname = cwd + fileSeparator;
147 else if (name[0] == '.' && (name[1] == '/' || name[1] == '\\') )
149 libname = cwd + fileSeparator + name.substr(2, name.length());
152 else if ( name[0] == '.' && name[1] == '.' /* && (name[2] == '/' || name[2] == '\\') */ )
154 if ( IsAtRoot(cwd) ) // hope it gets / (for Linux), C: D: (for Windows)
156 // if we are already at / or c: --> hopeless
158 std::cout << " File path [" << name << "] doesn't exist" << std::endl;
163 // iterate on ../ and go up from the current working dir!
165 bool alreadyProcessRoot = false;
167 //if (a[a.size()-1] != fileSeparator[0])
168 // a.append(fileSeparator);
169 //std::cout << "------------------a [" << a << "]" << std::endl;
171 for(;;) // wild loop !
173 std::string::size_type slash_position = cwd.find_last_of(fileSeparator);
174 if (slash_position != std::string::npos) {
175 if (slash_position == 0)
177 cwd = cwd.substr(0,slash_position/*+1*/);
178 //std::cout << "------------------cwd [" << cwd << "]" << std::endl;
184 a = a.substr(3, /*name.length()*/ a.length()); // remove ../
185 //std::cout << "------------------a [" << a << "]" << std::endl;
186 if (a == "" || alreadyProcessRoot)
189 std::cout << " File path : [" << name << "] doesn't exist" << std::endl;
193 // std::string b = cwd + a;
195 char c = cwd[cwd.size()-1];
196 if (c != '/' && c != '\\' )
197 libname += fileSeparator;
200 if ( a[0] != '.' ) // if . (probabely ../), loop again
204 alreadyProcessRoot = true;
206 } // end iterating on ../
208 //std::cout << "------------------out of loop]" << std::endl;
213 } // ----- End of expanding path name ( ./ ../ ../../ )
215 std::cout <<"* ERROR in ExpandLibName : should never get here!" << std::endl;
217 return(""); // Will never get here!
220 // ===================================================================================
222 std::string Utilities::MakeLibnameFromPath(std::string path, std::string pkgname)
224 std::string libname = path;
225 char c = path[path.size()-1];
226 #if defined(__GNUC__)
234 #elif defined(_WIN32)
236 libname = path+"\\bb";
243 // ===================================================================================
245 std::string Utilities::MakePkgnameFromPath(std::string path, std::string pkgname, bool addExt)
247 std::string libname = path;
248 char c = path[path.size()-1];
249 if (c != '/' && c != '\\')
251 libname += ConfigurationFile::GetInstance().Get_file_separator ();
256 int l = libname.size();
259 if (libname.substr(l-4, 4) != ".bbs")
261 libname = libname + ".bbs";
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)
273 #if defined(__GNUC__)
274 std::string str_home(getenv("HOME"));
275 #elif defined(_WIN32)
276 std::string str_home(getenv("USERPROFILE"));
278 std::string fullname = str_home + "/.bbtk/" + name;
279 Utilities::replace( fullname,
280 INVALID_FILE_SEPARATOR ,
281 VALID_FILE_SEPARATOR);
287 //========================================================================
289 bool Utilities::IsAtRoot(std::string cwd)
291 if ( cwd == "/" // hope it gets / (for Linux)
292 || (cwd.size() <= 3 && cwd[1] == ':') ) // hope it gets C: D: (for Windows)
298 // ======================================================================
300 bool Utilities::IsDirectory(std::string const &dirName)
304 if ( stat(dirName.c_str(), &fs) == 0 )
307 return ((fs.st_mode & _S_IFDIR) != 0);
309 return S_ISDIR(fs.st_mode);
318 // ===================================================================================
320 void Utilities::SplitAroundFirstDot( const std::string& in,
324 std::string delimiter = ".";
325 std::string::size_type pos = in.find_first_of(delimiter);
326 if (std::string::npos != pos)
328 left = in.substr(0,pos);
329 right = in.substr(pos+1,in.size());
334 // bbtkError(in<<" : expected 'a.b' format but no dot found");
339 //=======================================================================
340 void Utilities::SplitString ( const std::string& str,
341 const std::string& delimiters,
342 std::vector<std::string>& tokens)
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);
349 while (std::string::npos != pos || std::string::npos != lastPos)
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);
360 //=======================================================================
363 // ===================================================================================
365 std::string Utilities::get_file_name(const std::string& s)
367 std::string::size_type slash_position = s.find_last_of("/\\");
368 if (slash_position != std::string::npos)
370 return s.substr(slash_position+1,std::string::npos);
378 // ===================================================================================
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
385 int Utilities::Explore(std::string const &dirpath, bool recursive, std::vector<std::string> &Filenames)
387 int numberOfFiles = 0;
388 std::string fileName;
390 std::string dirName = dirpath;
393 WIN32_FIND_DATA fileData;
394 HANDLE hFile = FindFirstFile((dirName+"\\*").c_str(), &fileData);
396 for(BOOL b = (hFile != INVALID_HANDLE_VALUE); b;
397 b = FindNextFile(hFile, &fileData))
399 fileName = fileData.cFileName;
400 if ( fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
402 // Need to check for . and .. to avoid infinite loop
403 if ( fileName != "." && fileName != ".." && recursive )
405 numberOfFiles += Explore(dirName+ "\\"+fileName,recursive,Filenames);
410 Filenames.push_back(dirName+"\\"+fileName);
414 DWORD dwError = GetLastError();
415 if (hFile != INVALID_HANDLE_VALUE)
417 if (dwError != ERROR_NO_MORE_FILES)
420 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
421 FORMAT_MESSAGE_FROM_SYSTEM|
422 FORMAT_MESSAGE_IGNORE_INSERTS,
424 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
425 (LPTSTR) &lpMsgBuf,0,NULL);
427 // ErrorMacro("FindNextFile error. Error is " << (char *)lpMsgBuf
428 // <<" for the directory : "<<dirName);
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());
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.
450 for (d = readdir(dir); d; d = readdir(dir))
452 fileName = dirName + "/" + d->d_name;
453 //std::cout <<"in Explor filename[" << fileName << "]" << std::endl;
454 if( stat(fileName.c_str(), &buf) != 0 )
456 //ErrorMacro( strerror(errno) );
458 if ( S_ISREG(buf.st_mode) ) //is it a regular file?
460 Filenames.push_back( fileName );
463 else if ( S_ISDIR(buf.st_mode) ) //directory?
465 if ( d->d_name[0] != '.' && recursive ) //we also skip hidden files
467 numberOfFiles += Explore( fileName, recursive, Filenames);
472 //ErrorMacro( "Unexpected error" );
476 if( closedir(dir) != 0 )
478 // ErrorMacro( strerror(errno) );
482 return numberOfFiles;
487 //=======================================================================
488 // Replaces substrings "\\n" by a real carriage return "\n"
489 void Utilities::SubsBackslashN ( std::string& s )
491 std::string ss("\\n");
492 std::string::size_type pos = 0;
495 while ( pos != std::string::npos )
497 s.replace(pos,2,cr,1);
498 pos = s.find(ss, pos-1);
501 //=======================================================================
505 bool Utilities::loosematch(std::string stdLine,std::string stdOptions)
508 std::vector<std::string> tokens;
509 SplitString ( stdOptions,"|", tokens);
510 int i,size=tokens.size();
511 for (i=0; i<size; i++)
514 if ( strcmpi(stdLine.c_str(),tokens[i].c_str())==0)
519 if ( strcasecmp(stdLine.c_str(),tokens[i].c_str())==0)