Optimize KWSys SystemTools::FileExists on Windows

We optimize this method by using the GetFileAttributesExA native Windows
API to check for file existence when possible.  For real Windows builds
we always use it.  For Cygwin we use cygwin_conv_to_win32_path to get a
native Windows path if possible and otherwise fall back to 'access'.

Cygwin-to-Windows path conversion and cache by Wojciech Migda.
See issue #8826.
This commit is contained in:
Brad King 2009-09-22 13:02:20 -04:00
parent 664a409ae0
commit 9b6c3d0782
2 changed files with 81 additions and 24 deletions

View File

@ -65,10 +65,15 @@
#endif #endif
// Windows API. Some parts used even on cygwin. // Windows API. Some parts used even on cygwin.
#if defined(_WIN32) #if defined(_WIN32) || defined (__CYGWIN__)
# include <windows.h> # include <windows.h>
#endif #endif
#ifdef __CYGWIN__
# undef _WIN32
extern "C" void cygwin_conv_to_win32_path(const char *path, char *win32_path);
#endif
// getpwnam doesn't exist on Windows and Cray Xt3/Catamount // getpwnam doesn't exist on Windows and Cray Xt3/Catamount
// same for TIOCGWINSZ // same for TIOCGWINSZ
#if defined(_WIN32) || defined (__LIBCATAMOUNT__) #if defined(_WIN32) || defined (__LIBCATAMOUNT__)
@ -892,40 +897,70 @@ bool SystemTools::SameFile(const char* file1, const char* file2)
#endif #endif
} }
//----------------------------------------------------------------------------
#if defined(_WIN32) || defined(__CYGWIN__)
static bool WindowsFileExists(const char* filename)
{
WIN32_FILE_ATTRIBUTE_DATA fd;
return GetFileAttributesExA(filename, GetFileExInfoStandard, &fd) != 0;
}
#endif
// return true if the file exists //----------------------------------------------------------------------------
bool SystemTools::FileExists(const char* filename)
{
if(!(filename && *filename))
{
return false;
}
#if defined(__CYGWIN__)
// Convert filename to native windows path if possible.
char winpath[MAX_PATH];
if(SystemTools::PathCygwinToWin32(filename, winpath))
{
return WindowsFileExists(winpath);
}
return access(filename, R_OK) == 0;
#elif defined(_WIN32)
return WindowsFileExists(filename);
#else
return access(filename, R_OK) == 0;
#endif
}
//----------------------------------------------------------------------------
bool SystemTools::FileExists(const char* filename, bool isFile) bool SystemTools::FileExists(const char* filename, bool isFile)
{ {
#ifdef _MSC_VER if(SystemTools::FileExists(filename))
# define access _access
#endif
#ifndef R_OK
# define R_OK 04
#endif
#ifdef __SYLLABLE__
if ((filename !=0) && (*filename == 0))
{
return false;
}
#endif
if ( access(filename, R_OK) != 0 )
{
return false;
}
else
{ {
// If isFile is set return not FileIsDirectory, // If isFile is set return not FileIsDirectory,
// so this will only be true if it is a file // so this will only be true if it is a file
if(isFile) return !isFile || !SystemTools::FileIsDirectory(filename);
{
return !SystemTools::FileIsDirectory(filename);
}
return true;
} }
return false;
} }
//----------------------------------------------------------------------------
#ifdef __CYGWIN__
bool SystemTools::PathCygwinToWin32(const char *path, char *win32_path)
{
SystemToolsTranslationMap::iterator i =
SystemTools::Cyg2Win32Map->find(path);
if (i != SystemTools::Cyg2Win32Map->end())
{
strncpy(win32_path, i->second.c_str(), MAX_PATH);
}
else
{
cygwin_conv_to_win32_path(path, win32_path);
SystemToolsTranslationMap::value_type entry(path, win32_path);
SystemTools::Cyg2Win32Map->insert(entry);
}
return win32_path[0] != 0;
}
#endif
bool SystemTools::Touch(const char* filename, bool create) bool SystemTools::Touch(const char* filename, bool create)
{ {
if(create && !SystemTools::FileExists(filename)) if(create && !SystemTools::FileExists(filename))
@ -4536,6 +4571,9 @@ bool SystemTools::ParseURL( const kwsys_stl::string& URL,
unsigned int SystemToolsManagerCount; unsigned int SystemToolsManagerCount;
SystemToolsTranslationMap *SystemTools::TranslationMap; SystemToolsTranslationMap *SystemTools::TranslationMap;
SystemToolsTranslationMap *SystemTools::LongPathMap; SystemToolsTranslationMap *SystemTools::LongPathMap;
#ifdef __CYGWIN__
SystemToolsTranslationMap *SystemTools::Cyg2Win32Map;
#endif
// SystemToolsManager manages the SystemTools singleton. // SystemToolsManager manages the SystemTools singleton.
// SystemToolsManager should be included in any translation unit // SystemToolsManager should be included in any translation unit
@ -4581,6 +4619,9 @@ void SystemTools::ClassInitialize()
// Allocate the translation map first. // Allocate the translation map first.
SystemTools::TranslationMap = new SystemToolsTranslationMap; SystemTools::TranslationMap = new SystemToolsTranslationMap;
SystemTools::LongPathMap = new SystemToolsTranslationMap; SystemTools::LongPathMap = new SystemToolsTranslationMap;
#ifdef __CYGWIN__
SystemTools::Cyg2Win32Map = new SystemToolsTranslationMap;
#endif
// Add some special translation paths for unix. These are not added // Add some special translation paths for unix. These are not added
// for windows because drive letters need to be maintained. Also, // for windows because drive letters need to be maintained. Also,
@ -4637,6 +4678,9 @@ void SystemTools::ClassFinalize()
{ {
delete SystemTools::TranslationMap; delete SystemTools::TranslationMap;
delete SystemTools::LongPathMap; delete SystemTools::LongPathMap;
#ifdef __CYGWIN__
delete SystemTools::Cyg2Win32Map;
#endif
} }

View File

@ -275,7 +275,17 @@ public:
* not a directory. If isFile = false, then return true * not a directory. If isFile = false, then return true
* if it is a file or a directory. * if it is a file or a directory.
*/ */
static bool FileExists(const char* filename, bool isFile=false); static bool FileExists(const char* filename, bool isFile);
static bool FileExists(const char* filename);
/**
* Converts Cygwin path to Win32 path. Uses dictionary container for
* caching and calls to cygwin_conv_to_win32_path from Cygwin dll
* for actual translation. Returns true on success, else false.
*/
#ifdef __CYGWIN__
static bool PathCygwinToWin32(const char *path, char *win32_path);
#endif
/** /**
* Return file length * Return file length
@ -890,6 +900,9 @@ private:
*/ */
static SystemToolsTranslationMap *TranslationMap; static SystemToolsTranslationMap *TranslationMap;
static SystemToolsTranslationMap *LongPathMap; static SystemToolsTranslationMap *LongPathMap;
#ifdef __CYGWIN__
static SystemToolsTranslationMap *Cyg2Win32Map;
#endif
friend class SystemToolsManager; friend class SystemToolsManager;
}; };