/* This file is part of Highlight. Highlight is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Highlight is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Highlight. If not, see . */ #include "platform_fs.h" // includes for recursive getFileNames() function #ifdef _WIN32 #include #else #include #include #include #ifdef __VMS #include #include #include #include #include #include #endif /* __VMS */ #endif #include #include #include using namespace std; namespace Platform { #ifdef _WIN32 #include const char pathSeparator = '\\'; std::string getAppPath() { char pathAndName[MAX_PATH], path[MAX_PATH], drive[3]; GetModuleFileName ( NULL, ( wchar_t* ) pathAndName, MAX_PATH ); _splitpath ( pathAndName, drive, path, 0, 0 ); return std::string ( drive ) +path; } #else const char pathSeparator = '/'; std::string getAppPath() { return ""; } #endif bool getDirectoryEntries ( vector &fileList, string wildcard, bool recursiveSearch ) { if ( !wildcard.empty() ) { string directory_path; string::size_type Pos = wildcard.find_last_of ( pathSeparator ); if ( Pos == string::npos ) { directory_path = "."; } else { directory_path = wildcard.substr ( 0, Pos + 1 ); wildcard = wildcard.substr ( Pos + 1 ); } /* old method using dirstream: dirstr::dirstream str( directory_path.c_str(), #ifdef USE_FN_MATCH dirstr::pred_f(FnMatcher(wildcard.c_str(), 0)), #else dirstr::pattern_f(wildcard.c_str()), #endif (recursiveSearch)?dirstr::recursive_yes:dirstr::recursive_no); for(string entry; str >> entry;) { fileList.push_back(dirstr::full_path(entry)); //cerr << "1: "< &fileName ) { vector subDirectory; // sub directories of directory WIN32_FIND_DATA FindFileData; // for FindFirstFile and FindNextFile // Find the first file in the directory string firstFile = directory + "\\*"; HANDLE hFind = FindFirstFile ( firstFile.c_str(), &FindFileData ); if ( hFind == INVALID_HANDLE_VALUE ) return; //error("Cannot open directory", directory.c_str()); // save files and sub directories do { // skip hidden or read only if ( FindFileData.cFileName[0] == '.' || ( FindFileData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ) || ( FindFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY ) ) continue; // if a sub directory and recursive, save sub directory if ( ( FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) && true /*g_isRecursive*/ ) { string subDirectoryPath = directory + pathSeparator + FindFileData.cFileName; //if (isPathExclued(subDirectoryPath)) //{ // if (!g_isQuiet) // cout << "exclude " << subDirectoryPath.substr(g_mainDirectoryLength) << endl; //} //else subDirectory.push_back ( subDirectoryPath ); continue; } // save the file name string filePathName = directory + pathSeparator + FindFileData.cFileName; // check exclude before wildcmp to avoid "unmatched exclude" error //bool isExcluded = isPathExclued(filePathName); // save file name if wildcard match if ( wildcmp ( wildcard.c_str(), FindFileData.cFileName ) ) { //if (isExcluded) // cout << "exclude " << filePathName.substr(g_mainDirectoryLength) << endl; //else fileName.push_back ( filePathName ); } } while ( FindNextFile ( hFind, &FindFileData ) != 0 ); // check for processing error FindClose ( hFind ); DWORD dwError = GetLastError(); if ( dwError != ERROR_NO_MORE_FILES ) return; //error("Error processing directory", directory.c_str()); // recurse into sub directories // if not doing recursive subDirectory is empty for ( unsigned i = 0; i < subDirectory.size(); i++ ) { // cout << "directory " << subDirectory[i] << endl; getFileNames ( subDirectory[i], wildcard, fileName ); continue; } return; } #else // not _WIN32 /** * LINUX function to resolve wildcards and recurse into sub directories. * The fileName vector is filled with the path and names of files to process. * * @param directory The path of the directory to be processed. * @param wildcard The wildcard to be processed (e.g. *.cpp). * @param filenam An empty vector which will be filled with the path and names of files to process. */ void getFileNames ( const string &directory,const string &wildcard, vector &fileName ) { struct dirent *entry; // entry from readdir() struct stat statbuf; // entry from stat() vector subDirectory; // sub directories of this directory // errno is defined in and is set for errors in opendir, readdir, or stat errno = 0; DIR *dp = opendir ( directory.c_str() ); if ( errno ) return; //error("Cannot open directory", directory.c_str()); // save the first fileName entry for this recursion const unsigned firstEntry = fileName.size(); // save files and sub directories while ( ( entry = readdir ( dp ) ) != NULL ) { // get file status string entryFilepath = directory + pathSeparator + entry->d_name; stat ( entryFilepath.c_str(), &statbuf ); if ( errno ) return; //error("Error getting file status in directory", directory.c_str()); // skip hidden or read only if ( entry->d_name[0] == '.' || ! ( statbuf.st_mode & S_IWUSR ) ) continue; // if a sub directory and recursive, save sub directory if ( S_ISDIR ( statbuf.st_mode ) && /*g_isRecursive*/ true ) ///TODO { // if (isPathExclued(entryFilepath)) // cout << "exclude " << entryFilepath.substr(g_mainDirectoryLength) << endl; // else subDirectory.push_back ( entryFilepath ); continue; } // if a file, save file name if ( S_ISREG ( statbuf.st_mode ) ) { // check exclude before wildcmp to avoid "unmatched exclude" error // bool isExcluded = isPathExclued(entryFilepath); // save file name if wildcard match if ( wildcmp ( wildcard.c_str(), entry->d_name ) ) { // if (isExcluded) // cout << "exclude " << entryFilepath.substr(g_mainDirectoryLength) << endl; // else fileName.push_back ( entryFilepath ); } } } closedir ( dp ); if ( errno ) return; //error("Error reading directory", directory.c_str()); // sort the current entries for fileName if ( firstEntry < fileName.size() ) sort ( &fileName[firstEntry], &fileName[fileName.size() ] ); // recurse into sub directories // if not doing recursive, subDirectory is empty if ( subDirectory.size() > 1 ) sort ( subDirectory.begin(), subDirectory.end() ); for ( unsigned i = 0; i < subDirectory.size(); i++ ) { getFileNames ( subDirectory[i], wildcard, fileName ); continue; } return; } #endif // From The Code Project http://www.codeproject.com/string/wildcmp.asp // Written by Jack Handy - jakkhandy@hotmail.com // Modified to compare case insensitive for Windows (the LC macro) int wildcmp ( const char *wild, const char *data ) { const char *cp = NULL, *mp = NULL; bool cmpval; while ( ( *data ) && ( *wild != '*' ) ) { #ifdef _WIN32 cmpval = ( tolower ( *wild ) != tolower ( *data ) ) && ( *wild != '?' ); #else cmpval = ( *wild != *data ) && ( *wild != '?' ); #endif if ( cmpval ) { return 0; } wild++; data++; } while ( *data ) { if ( *wild == '*' ) { if ( !*++wild ) { return 1; } mp = wild; cp = data+1; } else { #ifdef _WIN32 cmpval = ( tolower ( *wild ) == tolower ( *data ) || ( *wild == '?' ) ); #else cmpval = ( *wild == *data ) || ( *wild == '?' ); #endif if ( cmpval ) { wild++; data++; } else { wild = mp; data = cp++; } } } while ( *wild == '*' ) { wild++; } return !*wild; } }