Mercurial > octave
changeset 28898:caf577e7ef43
__wglob__: Fix for argument containing directory (bug #59252).
* oct-glob.cc (find_files): New function. Recursively find wildcards in
directory components and file name.
(windows_glob): Separate first directory component (or file name) and call
new function.
author | Markus Mützel <markus.muetzel@gmx.de> |
---|---|
date | Mon, 12 Oct 2020 17:14:08 +0200 |
parents | 6ac35698c99a |
children | f8efd03a553e |
files | liboctave/util/oct-glob.cc |
diffstat | 1 files changed, 65 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- a/liboctave/util/oct-glob.cc Mon Oct 12 08:39:05 2020 -0700 +++ b/liboctave/util/oct-glob.cc Mon Oct 12 17:14:08 2020 +0200 @@ -33,6 +33,7 @@ #include "glob-wrappers.h" #include "oct-glob.h" +#include "file-ops.h" #include "file-stat.h" #include "unwind-prot.h" @@ -149,6 +150,48 @@ return retval.sort (); } +#if defined (OCTAVE_USE_WINDOWS_API) + + static void + find_files (std::list<std::string>& dirlist, const std::string& dir, + const std::string& pat, const std::string& file) + { + // find first file in directory that matches pattern in PAT + std::wstring wpat = u8_to_wstring (sys::file_ops::concat (dir, pat)); + _WIN32_FIND_DATAW ffd; + HANDLE h_find = FindFirstFileW (wpat.c_str (), &ffd); + // ignore any error + if (h_find == INVALID_HANDLE_VALUE) + return; + + unwind_action close_h_find ([=] () { FindClose (h_find); }); + + // find all files that match pattern + do + { + std::string found_dir = u8_from_wstring (ffd.cFileName); + + if (file.empty ()) + dirlist.push_back (sys::file_ops::concat (dir, found_dir)); + else + { + // get next component of path (or file name) + size_t sep_pos = file.find_first_of (sys::file_ops::dir_sep_chars ()); + std::string pat_str = file.substr (0, sep_pos); + std::string file_str = (sep_pos != std::string::npos + && file.length () > sep_pos+1) + ? file.substr (sep_pos+1) : ""; + + // call this function recursively with next path component in PAT + find_files (dirlist, sys::file_ops::concat (dir, found_dir), + pat_str, file_str); + } + } + while (FindNextFileW (h_find, &ffd) != 0); + } + +#endif + // Glob like Windows "dir". Treat only * and ? as wildcards, // and "*.*" matches filenames even if they do not contain ".". string_vector @@ -160,8 +203,7 @@ #if defined (OCTAVE_USE_WINDOWS_API) - _WIN32_FIND_DATAW ffd; - std::list<std::string> dirlist_str; + std::list<std::string> dirlist; for (int i = 0; i < npat; i++) { @@ -169,22 +211,31 @@ if (xpat.empty ()) continue; - // find first file in directory that matches pattern - std::wstring wxpat = u8_to_wstring (xpat); - HANDLE h_find = FindFirstFileW (wxpat.c_str (), &ffd); - // ignore any error - if (h_find == INVALID_HANDLE_VALUE) - continue; + // separate component until first dir separator + size_t sep_pos + = xpat.find_first_of (sys::file_ops::dir_sep_chars ()); + std::string file = (sep_pos != std::string::npos + && xpat.length () > sep_pos+1) + ? xpat.substr (sep_pos+1) : ""; + xpat = xpat.substr (0, sep_pos); + + std::string dir = ""; - unwind_action close_h_find ([=] () { FindClose (h_find); }); + if (sep_pos == 2 && xpat[1] == ':') + { + // include disc root + sep_pos = file.find_first_of (sys::file_ops::dir_sep_chars ()); + dir = xpat; + xpat = file.substr (0, sep_pos); + file = (sep_pos != std::string::npos + && file.length () > sep_pos+1) + ? file.substr (sep_pos+1) : ""; + } - // find all other files that match pattern - do - dirlist_str.push_back (u8_from_wstring (ffd.cFileName)); - while (FindNextFileW (h_find, &ffd) != 0); + find_files (dirlist, dir, xpat, file); } - retval = string_vector (dirlist_str); + retval = string_vector (dirlist); #else