Jelajahi Sumber

Merge branch 'upstream-KWSys' into update-kwsys

# By KWSys Upstream
* upstream-KWSys:
  KWSys 2022-01-22 (16e180ad)
Brad King 3 tahun lalu
induk
melakukan
ecd5a18928

+ 1 - 0
Source/kwsys/CMakeLists.txt

@@ -192,6 +192,7 @@ endif()
 if(KWSYS_USE_Directory)
   set(KWSYS_USE_Encoding 1)
   set(KWSYS_USE_Status 1)
+  set(KWSYS_USE_SystemTools 1)
 endif()
 if(KWSYS_USE_DynamicLoader)
   set(KWSYS_USE_Encoding 1)

+ 75 - 15
Source/kwsys/Directory.cxx

@@ -7,6 +7,8 @@
 
 #include KWSYS_HEADER(Encoding.hxx)
 
+#include KWSYS_HEADER(SystemTools.hxx)
+
 // Work-around CMake dependency scanning limitation.  This must
 // duplicate the above list of headers.
 #if 0
@@ -16,15 +18,48 @@
 #endif
 
 #include <string>
+#include <utility>
 #include <vector>
 
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#  include <windows.h>
+
+#  include <ctype.h>
+#  include <fcntl.h>
+#  include <io.h>
+#  include <stdio.h>
+#  include <stdlib.h>
+#  include <string.h>
+#  include <sys/stat.h>
+#  include <sys/types.h>
+#endif
+
 namespace KWSYS_NAMESPACE {
 
 class DirectoryInternals
 {
 public:
+  struct FileData
+  {
+    std::string Name;
+#if defined(_WIN32) && !defined(__CYGWIN__)
+    _wfinddata_t FindData;
+#endif
+    FileData(std::string name
+#if defined(_WIN32) && !defined(__CYGWIN__)
+             ,
+             _wfinddata_t data
+#endif
+             )
+      : Name(std::move(name))
+#if defined(_WIN32) && !defined(__CYGWIN__)
+      , FindData(std::move(data))
+#endif
+    {
+    }
+  };
   // Array of Files
-  std::vector<std::string> Files;
+  std::vector<FileData> Files;
 
   // Path to Open'ed directory
   std::string Path;
@@ -59,10 +94,45 @@ unsigned long Directory::GetNumberOfFiles() const
 
 const char* Directory::GetFile(unsigned long dindex) const
 {
-  if (dindex >= this->Internal->Files.size()) {
-    return nullptr;
+  return this->Internal->Files[dindex].Name.c_str();
+}
+
+std::string const& Directory::GetFileName(std::size_t i) const
+{
+  return this->Internal->Files[i].Name;
+}
+
+std::string Directory::GetFilePath(std::size_t i) const
+{
+  std::string abs = this->Internal->Path;
+  if (!abs.empty() && abs.back() != '/') {
+    abs += '/';
   }
-  return this->Internal->Files[dindex].c_str();
+  abs += this->Internal->Files[i].Name;
+  return abs;
+}
+
+bool Directory::FileIsDirectory(std::size_t i) const
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+  _wfinddata_t const& data = this->Internal->Files[i].FindData;
+  return (data.attrib & FILE_ATTRIBUTE_DIRECTORY) != 0;
+#else
+  std::string const& path = this->GetFilePath(i);
+  return kwsys::SystemTools::FileIsDirectory(path);
+#endif
+}
+
+bool Directory::FileIsSymlink(std::size_t i) const
+{
+  std::string const& path = this->GetFilePath(i);
+#if defined(_WIN32) && !defined(__CYGWIN__)
+  _wfinddata_t const& data = this->Internal->Files[i].FindData;
+  return kwsys::SystemTools::FileIsSymlinkWithAttr(
+    Encoding::ToWindowsExtendedPath(path), data.attrib);
+#else
+  return kwsys::SystemTools::FileIsSymlink(path);
+#endif
 }
 
 const char* Directory::GetPath() const
@@ -81,16 +151,6 @@ void Directory::Clear()
 // First Windows platforms
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
-#  include <windows.h>
-
-#  include <ctype.h>
-#  include <fcntl.h>
-#  include <io.h>
-#  include <stdio.h>
-#  include <stdlib.h>
-#  include <string.h>
-#  include <sys/stat.h>
-#  include <sys/types.h>
 
 namespace KWSYS_NAMESPACE {
 
@@ -133,7 +193,7 @@ Status Directory::Load(std::string const& name, std::string* errorMessage)
 
   // Loop through names
   do {
-    this->Internal->Files.push_back(Encoding::ToNarrow(data.name));
+    this->Internal->Files.emplace_back(Encoding::ToNarrow(data.name), data);
   } while (_wfindnext(srchHandle, &data) != -1);
   this->Internal->Path = name;
   if (_findclose(srchHandle) == -1) {

+ 21 - 0
Source/kwsys/Directory.hxx.in

@@ -6,6 +6,7 @@
 #include <@KWSYS_NAMESPACE@/Configure.h>
 #include <@KWSYS_NAMESPACE@/Status.hxx>
 
+#include <cstddef>
 #include <string>
 
 namespace @KWSYS_NAMESPACE@ {
@@ -54,6 +55,26 @@ public:
    */
   const char* GetFile(unsigned long) const;
 
+  /**
+   * Return the name of the file at the given 0-based index.
+   */
+  std::string const& GetFileName(std::size_t i) const;
+
+  /**
+   * Return the absolute path to the file at the given 0-based index.
+   */
+  std::string GetFilePath(std::size_t i) const;
+
+  /**
+   * Return whether the file at the given 0-based index is a directory.
+   */
+  bool FileIsDirectory(std::size_t i) const;
+
+  /**
+   * Return whether the file at the given 0-based index is a symlink.
+   */
+  bool FileIsSymlink(std::size_t i) const;
+
   /**
    * Return the path to Open'ed directory
    */

+ 2 - 2
Source/kwsys/Glob.cxx

@@ -213,8 +213,8 @@ bool Glob::RecurseDirectory(std::string::size_type start,
     fname = kwsys::SystemTools::LowerCase(fname);
 #endif
 
-    bool isDir = kwsys::SystemTools::FileIsDirectory(realname);
-    bool isSymLink = kwsys::SystemTools::FileIsSymlink(realname);
+    bool isDir = d.FileIsDirectory(cc);
+    bool isSymLink = d.FileIsSymlink(cc);
 
     if (isDir && (!isSymLink || this->RecurseThroughSymlinks)) {
       if (isSymLink) {

+ 14 - 7
Source/kwsys/SystemTools.cxx

@@ -2287,7 +2287,7 @@ bool SystemTools::FilesDiffer(const std::string& source,
   if (statSource.nFileSizeHigh == 0 && statSource.nFileSizeLow == 0) {
     return false;
   }
-  off_t nleft =
+  auto nleft =
     ((__int64)statSource.nFileSizeHigh << 32) + statSource.nFileSizeLow;
 
 #else
@@ -3085,11 +3085,10 @@ bool SystemTools::FileIsExecutable(const std::string& name)
   return !FileIsDirectory(name) && TestFileAccess(name, TEST_FILE_EXECUTE);
 }
 
-bool SystemTools::FileIsSymlink(const std::string& name)
-{
 #if defined(_WIN32)
-  std::wstring path = Encoding::ToWindowsExtendedPath(name);
-  DWORD attr = GetFileAttributesW(path.c_str());
+bool SystemTools::FileIsSymlinkWithAttr(const std::wstring& path,
+                                        unsigned long attr)
+{
   if (attr != INVALID_FILE_ATTRIBUTES) {
     if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
       // FILE_ATTRIBUTE_REPARSE_POINT means:
@@ -3118,9 +3117,17 @@ bool SystemTools::FileIsSymlink(const std::string& name)
         (reparseTag == IO_REPARSE_TAG_MOUNT_POINT);
     }
     return false;
-  } else {
-    return false;
   }
+
+  return false;
+}
+#endif
+
+bool SystemTools::FileIsSymlink(const std::string& name)
+{
+#if defined(_WIN32)
+  std::wstring path = Encoding::ToWindowsExtendedPath(name);
+  return FileIsSymlinkWithAttr(path, GetFileAttributesW(path.c_str()));
 #else
   struct stat fs;
   if (lstat(name.c_str(), &fs) == 0) {

+ 10 - 0
Source/kwsys/SystemTools.hxx.in

@@ -688,6 +688,16 @@ public:
    */
   static bool FileIsExecutable(const std::string& name);
 
+#if defined(_WIN32)
+  /**
+   * Return true if the file with FileAttributes `attr` is a symlink
+   * Only available on Windows. This avoids an expensive `GetFileAttributesW`
+   * call.
+   */
+  static bool FileIsSymlinkWithAttr(const std::wstring& path,
+                                    unsigned long attr);
+#endif
+
   /**
    * Return true if the file is a symlink
    */