diff --git a/src/common/FSNodeZIP.cxx b/src/common/FSNodeZIP.cxx index acbc1fc3c..891d77945 100644 --- a/src/common/FSNodeZIP.cxx +++ b/src/common/FSNodeZIP.cxx @@ -43,7 +43,7 @@ FSNodeZIP::FSNodeZIP(const string& p) if (home != nullptr) _zipFile.replace(0, 1, home); #elif defined(BSPF_WINDOWS) - _zipFile.replace(0, 1, myHomeFinder.getHomePath()); + _zipFile.replace(0, 1, HomeFinder::getHomePath()); #endif } diff --git a/src/os/windows/FSNodeWINDOWS.cxx b/src/os/windows/FSNodeWINDOWS.cxx index 37ef0dbda..6984e1da7 100644 --- a/src/os/windows/FSNodeWINDOWS.cxx +++ b/src/os/windows/FSNodeWINDOWS.cxx @@ -16,69 +16,47 @@ //============================================================================ #include -#pragma warning( disable : 4091 ) +#pragma warning(disable : 4091) #include #include #include - -// F_OK, R_OK and W_OK are not defined under MSVC, so we define them here -// For more information on the modes used by MSVC, check: -// http://msdn2.microsoft.com/en-us/library/1w06ktdy(VS.80).aspx -#ifndef F_OK - #define F_OK 0 -#endif - -#ifndef R_OK - #define R_OK 4 -#endif - -#ifndef W_OK - #define W_OK 2 -#endif +#include #include "Windows.hxx" #include "FSNodeWINDOWS.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool FSNodeWINDOWS::exists() const +FSNodeWINDOWS::FSNodeWINDOWS(const string& p) + : _path{p.length() > 0 ? p : "~"} // Default to home directory { - return _access(_path.c_str(), F_OK) == 0; -} + // Expand '~' to the users 'home' directory + if (_path[0] == '~') + _path.replace(0, 1, HomeFinder::getHomePath()); -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool FSNodeWINDOWS::isReadable() const -{ - return _access(_path.c_str(), R_OK) == 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool FSNodeWINDOWS::isWritable() const -{ - return _access(_path.c_str(), W_OK) == 0; + setFlags(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FSNodeWINDOWS::setFlags() { // Get absolute path - TCHAR buf[4096]; - if(GetFullPathName(_path.c_str(), 4096, buf, NULL)) + TCHAR buf[MAX_PATH]; + if(GetFullPathName(_path.c_str(), MAX_PATH - 1, buf, NULL)) _path = buf; _displayName = lastPathComponent(_path); // Check whether it is a directory, and whether the file actually exists - const DWORD fileAttribs = GetFileAttributes(toUnicode(_path.c_str())); + const DWORD fileAttribs = GetFileAttributes(_path.c_str()); if(fileAttribs == INVALID_FILE_ATTRIBUTES) { - _isDirectory = _isFile = _isValid = false; + _isDirectory = _isFile = false; } else { _isDirectory = ((fileAttribs & FILE_ATTRIBUTE_DIRECTORY) != 0); _isFile = !_isDirectory;//((fileAttribs & FILE_ATTRIBUTE_NORMAL) != 0); - _isValid = true; // Add a trailing backslash, if necessary if (_isDirectory && _path.length() > 0 && _path[_path.length()-1] != '\\') @@ -87,83 +65,11 @@ void FSNodeWINDOWS::setFlags() _isPseudoRoot = false; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void FSNodeWINDOWS::addFile(AbstractFSList& list, ListMode mode, - const char* base, WIN32_FIND_DATA* find_data) -{ - FSNodeWINDOWS entry; - const char* const asciiName = toAscii(find_data->cFileName); - bool isDirectory = false, isFile = false; - - // Skip local directory (.) and parent (..) - if(!strncmp(asciiName, ".", 1) || !strncmp(asciiName, "..", 2)) - return; - - isDirectory = ((find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true : false); - isFile = !isDirectory;//(find_data->dwFileAttributes & FILE_ATTRIBUTE_NORMAL ? true : false); - - if((isFile && mode == FSNode::ListMode::DirectoriesOnly) || - (isDirectory && mode == FSNode::ListMode::FilesOnly)) - return; - - entry._isDirectory = isDirectory; - entry._isFile = isFile; - entry._displayName = asciiName; - entry._path = base; - entry._path += asciiName; - if(entry._isDirectory) - entry._path += "\\"; - entry._isValid = true; - entry._isPseudoRoot = false; - - list.emplace_back(make_shared(entry)); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -char* FSNodeWINDOWS::toAscii(TCHAR* str) -{ -#ifndef UNICODE - return str; -#else - static char asciiString[MAX_PATH]; - WideCharToMultiByte(CP_ACP, 0, str, _tcslen(str) + 1, asciiString, sizeof(asciiString), NULL, NULL); - return asciiString; -#endif -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const TCHAR* FSNodeWINDOWS::toUnicode(const char* str) -{ -#ifndef UNICODE - return str; -#else - static TCHAR unicodeString[MAX_PATH]; - MultiByteToWideChar(CP_ACP, 0, str, strlen(str) + 1, unicodeString, sizeof(unicodeString) / sizeof(TCHAR)); - return unicodeString; -#endif -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -FSNodeWINDOWS::FSNodeWINDOWS() -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -FSNodeWINDOWS::FSNodeWINDOWS(const string& p) - : _path{p.length() > 0 ? p : "~"} // Default to home directory -{ - // Expand '~' to the users 'home' directory - if(_path[0] == '~') - _path.replace(0, 1, myHomeFinder.getHomePath()); - - setFlags(); -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - string FSNodeWINDOWS::getShortPath() const { // If the path starts with the home directory, replace it with '~' - const string& home = myHomeFinder.getHomePath(); + const string& home = HomeFinder::getHomePath(); if(home != "" && BSPF::startsWithIgnoreCase(_path, home)) { string path = "~"; @@ -176,8 +82,35 @@ string FSNodeWINDOWS::getShortPath() const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool FSNodeWINDOWS:: - getChildren(AbstractFSList& myList, ListMode mode) const +size_t FSNodeWINDOWS::getSize() const +{ + if (_size == 0) + { + struct _stat st; + _size = _stat(_path.c_str(), &st) == 0 ? st.st_size : 0; + } + return _size; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +AbstractFSNodePtr FSNodeWINDOWS::getParent() const +{ + if (_isPseudoRoot) + return nullptr; + + if (_path.size() > 3) + { + const char* start = _path.c_str(); + const char* end = lastPathComponent(_path); + + return make_shared(string(start, static_cast(end - start))); + } + else + return make_shared(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool FSNodeWINDOWS::getChildren(AbstractFSList& myList, ListMode mode) const { assert(_isDirectory); @@ -193,14 +126,13 @@ bool FSNodeWINDOWS:: FSNodeWINDOWS entry; char drive_name[2] = { 0, 0 }; - drive_name[0] = toAscii(current_drive)[0]; + drive_name[0] = current_drive[0]; drive_name[1] = '\0'; entry._displayName = drive_name; entry._isDirectory = true; entry._isFile = false; - entry._isValid = true; entry._isPseudoRoot = false; - entry._path = toAscii(current_drive); + entry._path = current_drive; myList.emplace_back(make_shared(entry)); } } @@ -229,10 +161,52 @@ bool FSNodeWINDOWS:: } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -size_t FSNodeWINDOWS::getSize() const +void FSNodeWINDOWS::addFile(AbstractFSList& list, ListMode mode, + const char* base, const WIN32_FIND_DATA* find_data) { - struct _stat st; - return _stat(_path.c_str(), &st) == 0 ? st.st_size : 0; + const char* const asciiName = find_data->cFileName; + bool isDirectory = false, isFile = false; + + // Skip local directory (.) and parent (..) + if (!strncmp(asciiName, ".", 1) || !strncmp(asciiName, "..", 2)) + return; + + isDirectory = static_cast(find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); + isFile = !isDirectory;//(find_data->dwFileAttributes & FILE_ATTRIBUTE_NORMAL ? true : false); + + if ((isFile && mode == FSNode::ListMode::DirectoriesOnly) || + (isDirectory && mode == FSNode::ListMode::FilesOnly)) + return; + + FSNodeWINDOWS entry; + entry._isDirectory = isDirectory; + entry._isFile = isFile; + entry._displayName = asciiName; + entry._path = base; + entry._path += asciiName; + if (entry._isDirectory) + entry._path += "\\"; + entry._isPseudoRoot = false; + + list.emplace_back(make_shared(entry)); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool FSNodeWINDOWS::exists() const +{ + return _access(_path.c_str(), 0 /*F_OK*/) == 0; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool FSNodeWINDOWS::isReadable() const +{ + return _access(_path.c_str(), 4 /*R_OK*/) == 0; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool FSNodeWINDOWS::isWritable() const +{ + return _access(_path.c_str(), 2 /*W_OK*/) == 0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -258,20 +232,3 @@ bool FSNodeWINDOWS::rename(const string& newfile) else return false; } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -AbstractFSNodePtr FSNodeWINDOWS::getParent() const -{ - if(_isPseudoRoot) - return nullptr; - - if(_path.size() > 3) - { - const char* start = _path.c_str(); - const char* end = lastPathComponent(_path); - - return make_shared(string(start, static_cast(end - start))); - } - else - return make_shared(); -} diff --git a/src/os/windows/FSNodeWINDOWS.hxx b/src/os/windows/FSNodeWINDOWS.hxx index dfcb479ac..0ebe7566f 100644 --- a/src/os/windows/FSNodeWINDOWS.hxx +++ b/src/os/windows/FSNodeWINDOWS.hxx @@ -18,13 +18,9 @@ #ifndef FS_NODE_WINDOWS_HXX #define FS_NODE_WINDOWS_HXX -#include - #include "FSNode.hxx" #include "HomeFinder.hxx" -static HomeFinder myHomeFinder; - // TODO - fix isFile() functionality so that it actually determines if something // is a file; for now, it assumes a file if it isn't a directory @@ -41,9 +37,8 @@ class FSNodeWINDOWS : public AbstractFSNode * Creates a FSNodeWINDOWS with the root node as path. * * In regular windows systems, a virtual root path is used "". - * In windows CE, the "\" root is used instead. */ - FSNodeWINDOWS(); + FSNodeWINDOWS() : _isPseudoRoot{true}, _isDirectory{true} { } /** * Creates a FSNodeWINDOWS for a given path. @@ -62,7 +57,6 @@ class FSNodeWINDOWS : public AbstractFSNode void setName(const string& name) override { _displayName = name; } const string& getPath() const override { return _path; } string getShortPath() const override; - bool hasParent() const override { return !_isPseudoRoot; } bool isDirectory() const override { return _isDirectory; } bool isFile() const override { return _isFile; } bool isReadable() const override; @@ -71,16 +65,9 @@ class FSNodeWINDOWS : public AbstractFSNode bool rename(const string& newfile) override; size_t getSize() const override; - bool getChildren(AbstractFSList& list, ListMode mode) const override; + bool hasParent() const override { return !_isPseudoRoot; } AbstractFSNodePtr getParent() const override; - - protected: - string _displayName; - string _path; - bool _isDirectory{true}; - bool _isFile{false}; - bool _isPseudoRoot{true}; - bool _isValid{false}; + bool getChildren(AbstractFSList& list, ListMode mode) const override; private: /** @@ -98,23 +85,13 @@ class FSNodeWINDOWS : public AbstractFSNode * @param base String with the directory being listed. * @param find_data Describes a file that the FindFirstFile, FindFirstFileEx, or FindNextFile functions find. */ - static void addFile(AbstractFSList& list, ListMode mode, const char* base, WIN32_FIND_DATA* find_data); + static void addFile(AbstractFSList& list, ListMode mode, + const char* base, const WIN32_FIND_DATA* find_data); - /** - * Converts a Unicode string to Ascii format. - * - * @param str String to convert from Unicode to Ascii. - * @return str in Ascii format. - */ - static char* toAscii(TCHAR *str); - - /** - * Converts an Ascii string to Unicode format. - * - * @param str String to convert from Ascii to Unicode. - * @return str in Unicode format. - */ - static const TCHAR* toUnicode(const char* str); + private: + string _displayName, _path; + bool _isPseudoRoot{false}, _isDirectory{false}, _isFile{false}; + mutable size_t _size{0}; }; #endif diff --git a/src/os/windows/HomeFinder.hxx b/src/os/windows/HomeFinder.hxx index 1bc0a5778..a82ea243c 100644 --- a/src/os/windows/HomeFinder.hxx +++ b/src/os/windows/HomeFinder.hxx @@ -31,7 +31,7 @@ class HomeFinder ~HomeFinder() = default; // Return the 'APPDATA' folder, or an empty string if the folder couldn't be determined. - const string& getAppDataPath() const + static const string& getAppDataPath() { if(ourAppDataPath == "") { @@ -44,7 +44,7 @@ class HomeFinder } // Return the 'Desktop' folder, or an empty string if the folder couldn't be determined. - const string& getDesktopPath() const + static const string& getDesktopPath() { if(ourDesktopPath == "") { @@ -57,7 +57,7 @@ class HomeFinder } // Return the 'My Documents' folder, or an empty string if the folder couldn't be determined. - const string& getDocumentsPath() const + static const string& getDocumentsPath() { if(ourDocumentsPath == "") { @@ -70,7 +70,7 @@ class HomeFinder } // Return the 'HOME/User' folder, or an empty string if the folder couldn't be determined. - const string& getHomePath() const + static const string& getHomePath() { if(ourHomePath == "") {