comparison liboctave/util/oct-glob.cc @ 31607:aac27ad79be6 stable

maint: Re-indent code after switch to using namespace macros. * build-env.h, build-env.in.cc, Cell.h, __betainc__.cc, __eigs__.cc, __ftp__.cc, __ichol__.cc, __ilu__.cc, __isprimelarge__.cc, __magick_read__.cc, __pchip_deriv__.cc, amd.cc, base-text-renderer.cc, base-text-renderer.h, besselj.cc, bitfcns.cc, bsxfun.cc, c-file-ptr-stream.h, call-stack.cc, call-stack.h, ccolamd.cc, cellfun.cc, chol.cc, colamd.cc, dasrt.cc, data.cc, debug.cc, defaults.cc, defaults.h, det.cc, display.cc, display.h, dlmread.cc, dynamic-ld.cc, dynamic-ld.h, ellipj.cc, environment.cc, environment.h, error.cc, error.h, errwarn.h, event-manager.cc, event-manager.h, event-queue.cc, event-queue.h, fcn-info.cc, fcn-info.h, fft.cc, fft2.cc, file-io.cc, filter.cc, find.cc, ft-text-renderer.cc, ft-text-renderer.h, gcd.cc, gl-render.cc, gl-render.h, gl2ps-print.cc, gl2ps-print.h, graphics-toolkit.cc, graphics-toolkit.h, graphics.cc, gsvd.cc, gtk-manager.cc, gtk-manager.h, help.cc, help.h, hook-fcn.cc, hook-fcn.h, input.cc, input.h, interpreter-private.cc, interpreter-private.h, interpreter.cc, interpreter.h, inv.cc, jsondecode.cc, jsonencode.cc, latex-text-renderer.cc, latex-text-renderer.h, load-path.cc, load-path.h, load-save.cc, load-save.h, lookup.cc, ls-hdf5.cc, ls-mat4.cc, ls-mat5.cc, lsode.cc, lu.cc, mappers.cc, matrix_type.cc, max.cc, mex.cc, mexproto.h, mxarray.h, mxtypes.in.h, oct-errno.in.cc, oct-hdf5-types.cc, oct-hist.cc, oct-hist.h, oct-map.cc, oct-map.h, oct-opengl.h, oct-prcstrm.h, oct-process.cc, oct-process.h, oct-stdstrm.h, oct-stream.cc, oct-stream.h, oct-strstrm.h, octave-default-image.h, ordqz.cc, ordschur.cc, pager.cc, pager.h, pinv.cc, pow2.cc, pr-output.cc, psi.cc, qr.cc, quadcc.cc, rand.cc, regexp.cc, settings.cc, settings.h, sighandlers.cc, sighandlers.h, sparse-xpow.cc, sqrtm.cc, stack-frame.cc, stack-frame.h, stream-euler.cc, strfns.cc, svd.cc, syminfo.cc, syminfo.h, symrcm.cc, symrec.cc, symrec.h, symscope.cc, symscope.h, symtab.cc, symtab.h, sysdep.cc, sysdep.h, text-engine.cc, text-engine.h, text-renderer.cc, text-renderer.h, time.cc, toplev.cc, typecast.cc, url-handle-manager.cc, url-handle-manager.h, urlwrite.cc, utils.cc, utils.h, variables.cc, variables.h, xdiv.cc, __delaunayn__.cc, __init_fltk__.cc, __init_gnuplot__.cc, __ode15__.cc, __voronoi__.cc, audioread.cc, convhulln.cc, gzip.cc, cdef-class.cc, cdef-class.h, cdef-fwd.h, cdef-manager.cc, cdef-manager.h, cdef-method.cc, cdef-method.h, cdef-object.cc, cdef-object.h, cdef-package.cc, cdef-package.h, cdef-property.cc, cdef-property.h, cdef-utils.cc, cdef-utils.h, ov-base-diag.cc, ov-base-int.cc, ov-base-mat.cc, ov-base-mat.h, ov-base-scalar.cc, ov-base.cc, ov-base.h, ov-bool-mat.cc, ov-bool-mat.h, ov-bool-sparse.cc, ov-bool.cc, ov-builtin.h, ov-cell.cc, ov-ch-mat.cc, ov-class.cc, ov-class.h, ov-classdef.cc, ov-classdef.h, ov-complex.cc, ov-cx-diag.cc, ov-cx-mat.cc, ov-cx-sparse.cc, ov-dld-fcn.cc, ov-dld-fcn.h, ov-fcn-handle.cc, ov-fcn-handle.h, ov-fcn.h, ov-float.cc, ov-flt-complex.cc, ov-flt-cx-diag.cc, ov-flt-cx-mat.cc, ov-flt-re-diag.cc, ov-flt-re-mat.cc, ov-flt-re-mat.h, ov-intx.h, ov-java.cc, ov-lazy-idx.cc, ov-legacy-range.cc, ov-magic-int.cc, ov-mex-fcn.cc, ov-mex-fcn.h, ov-null-mat.cc, ov-perm.cc, ov-range.cc, ov-re-diag.cc, ov-re-mat.cc, ov-re-mat.h, ov-re-sparse.cc, ov-scalar.cc, ov-str-mat.cc, ov-struct.cc, ov-typeinfo.cc, ov-typeinfo.h, ov-usr-fcn.cc, ov-usr-fcn.h, ov.cc, ov.h, ovl.h, octave.cc, octave.h, op-b-sbm.cc, op-bm-sbm.cc, op-cs-scm.cc, op-fm-fcm.cc, op-fs-fcm.cc, op-s-scm.cc, op-scm-cs.cc, op-scm-s.cc, op-sm-cs.cc, ops.h, anon-fcn-validator.cc, anon-fcn-validator.h, bp-table.cc, bp-table.h, comment-list.cc, comment-list.h, filepos.h, lex.h, oct-lvalue.cc, oct-lvalue.h, parse.h, profiler.cc, profiler.h, pt-anon-scopes.cc, pt-anon-scopes.h, pt-arg-list.cc, pt-arg-list.h, pt-args-block.cc, pt-args-block.h, pt-array-list.cc, pt-array-list.h, pt-assign.cc, pt-assign.h, pt-binop.cc, pt-binop.h, pt-bp.cc, pt-bp.h, pt-cbinop.cc, pt-cbinop.h, pt-cell.cc, pt-cell.h, pt-check.cc, pt-check.h, pt-classdef.cc, pt-classdef.h, pt-cmd.h, pt-colon.cc, pt-colon.h, pt-const.cc, pt-const.h, pt-decl.cc, pt-decl.h, pt-eval.cc, pt-eval.h, pt-except.cc, pt-except.h, pt-exp.cc, pt-exp.h, pt-fcn-handle.cc, pt-fcn-handle.h, pt-id.cc, pt-id.h, pt-idx.cc, pt-idx.h, pt-jump.h, pt-loop.cc, pt-loop.h, pt-mat.cc, pt-mat.h, pt-misc.cc, pt-misc.h, pt-pr-code.cc, pt-pr-code.h, pt-select.cc, pt-select.h, pt-spmd.cc, pt-spmd.h, pt-stmt.cc, pt-stmt.h, pt-tm-const.cc, pt-tm-const.h, pt-unop.cc, pt-unop.h, pt-walk.cc, pt-walk.h, pt.cc, pt.h, token.cc, token.h, Range.cc, Range.h, idx-vector.cc, idx-vector.h, range-fwd.h, CollocWt.cc, CollocWt.h, aepbalance.cc, aepbalance.h, chol.cc, chol.h, gepbalance.cc, gepbalance.h, gsvd.cc, gsvd.h, hess.cc, hess.h, lo-mappers.cc, lo-mappers.h, lo-specfun.cc, lo-specfun.h, lu.cc, lu.h, oct-convn.cc, oct-convn.h, oct-fftw.cc, oct-fftw.h, oct-norm.cc, oct-norm.h, oct-rand.cc, oct-rand.h, oct-spparms.cc, oct-spparms.h, qr.cc, qr.h, qrp.cc, qrp.h, randgamma.cc, randgamma.h, randmtzig.cc, randmtzig.h, randpoisson.cc, randpoisson.h, schur.cc, schur.h, sparse-chol.cc, sparse-chol.h, sparse-lu.cc, sparse-lu.h, sparse-qr.cc, sparse-qr.h, svd.cc, svd.h, child-list.cc, child-list.h, dir-ops.cc, dir-ops.h, file-ops.cc, file-ops.h, file-stat.cc, file-stat.h, lo-sysdep.cc, lo-sysdep.h, lo-sysinfo.cc, lo-sysinfo.h, mach-info.cc, mach-info.h, oct-env.cc, oct-env.h, oct-group.cc, oct-group.h, oct-password.cc, oct-password.h, oct-syscalls.cc, oct-syscalls.h, oct-time.cc, oct-time.h, oct-uname.cc, oct-uname.h, action-container.cc, action-container.h, base-list.h, cmd-edit.cc, cmd-edit.h, cmd-hist.cc, cmd-hist.h, f77-fcn.h, file-info.cc, file-info.h, lo-array-errwarn.cc, lo-array-errwarn.h, lo-hash.cc, lo-hash.h, lo-ieee.h, lo-regexp.cc, lo-regexp.h, lo-utils.cc, lo-utils.h, oct-base64.cc, oct-base64.h, oct-glob.cc, oct-glob.h, oct-inttypes.h, oct-mutex.cc, oct-mutex.h, oct-refcount.h, oct-shlib.cc, oct-shlib.h, oct-sparse.cc, oct-sparse.h, oct-string.h, octave-preserve-stream-state.h, pathsearch.cc, pathsearch.h, quit.cc, quit.h, unwind-prot.cc, unwind-prot.h, url-transfer.cc, url-transfer.h: Re-indent code after switch to using namespace macros.
author Rik <rik@octave.org>
date Thu, 01 Dec 2022 18:02:15 -0800
parents e88a07dec498
children 597f3ee61a48
comparison
equal deleted inserted replaced
31605:e88a07dec498 31607:aac27ad79be6
51 // transforms the glob_match::glob function to be glob_match::rpl_glob, 51 // transforms the glob_match::glob function to be glob_match::rpl_glob,
52 // which is not what we want... 52 // which is not what we want...
53 53
54 OCTAVE_BEGIN_NAMESPACE(octave) 54 OCTAVE_BEGIN_NAMESPACE(octave)
55 55
56 static bool 56 static bool
57 single_match_exists (const std::string& file) 57 single_match_exists (const std::string& file)
58 { 58 {
59 sys::file_stat s (file); 59 sys::file_stat s (file);
60 60
61 return s.exists (); 61 return s.exists ();
62 } 62 }
63 63
64 OCTAVE_BEGIN_NAMESPACE(sys) 64 OCTAVE_BEGIN_NAMESPACE(sys)
65 65
66 bool 66 bool
67 fnmatch (const string_vector& pat, const std::string& str, int fnm_flags) 67 fnmatch (const string_vector& pat, const std::string& str, int fnm_flags)
68 {
69 int npat = pat.numel ();
70
71 const char *cstr = str.c_str ();
72
73 for (int i = 0; i < npat; i++)
74 if (octave_fnmatch_wrapper (pat(i).c_str (), cstr, fnm_flags)
75 != octave_fnm_nomatch_wrapper ())
76 return true;
77
78 return false;
79 }
80
81 string_vector
82 glob (const string_vector& pat)
83 {
84 string_vector retval;
85
86 int npat = pat.numel ();
87
88 int k = 0;
89
90 void *glob_info = octave_create_glob_info_struct ();
91
92 unwind_action cleanup_glob_info_struct
93 ([=] () { octave_destroy_glob_info_struct (glob_info); });
94
95 for (int i = 0; i < npat; i++)
68 { 96 {
69 int npat = pat.numel (); 97 std::string xpat = pat(i);
70 98
71 const char *cstr = str.c_str (); 99 if (! xpat.empty ())
72 100 {
73 for (int i = 0; i < npat; i++)
74 if (octave_fnmatch_wrapper (pat(i).c_str (), cstr, fnm_flags)
75 != octave_fnm_nomatch_wrapper ())
76 return true;
77
78 return false;
79 }
80
81 string_vector
82 glob (const string_vector& pat)
83 {
84 string_vector retval;
85
86 int npat = pat.numel ();
87
88 int k = 0;
89
90 void *glob_info = octave_create_glob_info_struct ();
91
92 unwind_action cleanup_glob_info_struct
93 ([=] () { octave_destroy_glob_info_struct (glob_info); });
94
95 for (int i = 0; i < npat; i++)
96 {
97 std::string xpat = pat(i);
98
99 if (! xpat.empty ())
100 {
101 #if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \ 101 #if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \
102 && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)) 102 && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))
103 std::replace (xpat.begin (), xpat.end (), '\\', '/'); 103 std::replace (xpat.begin (), xpat.end (), '\\', '/');
104 #endif 104 #endif
105 105
106 int err = octave_glob_wrapper (xpat.c_str (), 106 int err = octave_glob_wrapper (xpat.c_str (),
107 octave_glob_nosort_wrapper (), 107 octave_glob_nosort_wrapper (),
108 glob_info); 108 glob_info);
109 109
110 if (! err) 110 if (! err)
111 {
112 int n = octave_glob_num_matches (glob_info);
113
114 const char *const *matches
115 = octave_glob_match_list (glob_info);
116
117 // FIXME: we shouldn't have to check to see if
118 // a single match exists, but it seems that glob() won't
119 // check for us unless the pattern contains globbing
120 // characters. Hmm.
121
122 if (n > 1
123 || (n == 1
124 && single_match_exists (std::string (matches[0]))))
111 { 125 {
112 int n = octave_glob_num_matches (glob_info); 126 retval.resize (k+n);
113 127
114 const char * const *matches 128 for (int j = 0; j < n; j++)
115 = octave_glob_match_list (glob_info);
116
117 // FIXME: we shouldn't have to check to see if
118 // a single match exists, but it seems that glob() won't
119 // check for us unless the pattern contains globbing
120 // characters. Hmm.
121
122 if (n > 1
123 || (n == 1
124 && single_match_exists (std::string (matches[0]))))
125 { 129 {
126 retval.resize (k+n); 130 std::string tmp = matches[j];
127
128 for (int j = 0; j < n; j++)
129 {
130 std::string tmp = matches[j];
131 131
132 #if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \ 132 #if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \
133 && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM) 133 && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)
134 std::replace (tmp.begin (), tmp.end (), '/', '\\'); 134 std::replace (tmp.begin (), tmp.end (), '/', '\\');
135 #endif 135 #endif
136 136
137 retval[k++] = tmp; 137 retval[k++] = tmp;
138 }
139 } 138 }
140
141 octave_globfree_wrapper (glob_info);
142 } 139 }
143 } 140
144 } 141 octave_globfree_wrapper (glob_info);
145 142 }
146 return retval.sort (); 143 }
147 } 144 }
148 145
146 return retval.sort ();
147 }
148
149 #if defined (OCTAVE_USE_WINDOWS_API) 149 #if defined (OCTAVE_USE_WINDOWS_API)
150 150
151 static void 151 static void
152 find_files (std::list<std::string>& dirlist, const std::string& dir, 152 find_files (std::list<std::string>& dirlist, const std::string& dir,
153 const std::string& pat, std::string& file) 153 const std::string& pat, std::string& file)
154 {
155 // remove leading file separators
156 bool is_file_empty = file.empty ();
157 while (! file.empty () && sys::file_ops::is_dir_sep (file[0]))
158 file = file.substr (1, std::string::npos);
159
160 bool is_trailing_file_sep = ! is_file_empty && file.empty ();
161
162 if (! pat.compare (".") || ! pat.compare (".."))
154 { 163 {
155 // remove leading file separators 164 // shortcut for trivial patterns that would expand to a folder name
156 bool is_file_empty = file.empty (); 165
157 while (! file.empty () && sys::file_ops::is_dir_sep (file[0])) 166 // get next component of path (or file name)
158 file = file.substr (1, std::string::npos); 167 std::size_t sep_pos
159 168 = file.find_first_of (sys::file_ops::dir_sep_chars ());
160 bool is_trailing_file_sep = ! is_file_empty && file.empty (); 169 std::string pat_str = file.substr (0, sep_pos);
161 170 std::string file_str = (sep_pos != std::string::npos)
162 if (! pat.compare (".") || ! pat.compare ("..")) 171 ? file.substr (sep_pos) : "";
163 { 172
164 // shortcut for trivial patterns that would expand to a folder name 173 // Original pattern ends with "." or "..". Take it as we have it.
165 174 if (pat_str.empty ())
175 {
176 if (is_trailing_file_sep)
177 pat_str = sys::file_ops::dir_sep_char ();
178 dirlist.push_back (sys::file_ops::concat (dir, pat) + pat_str);
179 return;
180 }
181
182 // call this function recursively with next path component in PAT
183 find_files (dirlist, sys::file_ops::concat (dir, pat),
184 pat_str, file_str);
185 return;
186 }
187
188 // find first file in directory that matches pattern in PAT
189 std::wstring wpat = u8_to_wstring (sys::file_ops::concat (dir, pat));
190 _WIN32_FIND_DATAW ffd;
191 HANDLE h_find = FindFirstFileW (wpat.c_str (), &ffd);
192 // ignore any error
193 if (h_find == INVALID_HANDLE_VALUE)
194 return;
195
196 unwind_action close_h_find ([=] () { FindClose (h_find); });
197
198 // find all files that match pattern
199 do
200 {
201 // must be directory if pattern continues
202 if (! (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
203 && (! file.empty () || is_trailing_file_sep))
204 continue;
205
206 std::string found_dir = u8_from_wstring (ffd.cFileName);
207
208 if (file.empty ())
209 {
210 // Don't include "." and ".." in matches.
211 if (found_dir.compare (".") && found_dir.compare (".."))
212 {
213 if (is_trailing_file_sep)
214 found_dir += sys::file_ops::dir_sep_char ();
215 dirlist.push_back (sys::file_ops::concat (dir, found_dir));
216 }
217 }
218 else
219 {
166 // get next component of path (or file name) 220 // get next component of path (or file name)
167 std::size_t sep_pos 221 std::size_t sep_pos
168 = file.find_first_of (sys::file_ops::dir_sep_chars ()); 222 = file.find_first_of (sys::file_ops::dir_sep_chars ());
169 std::string pat_str = file.substr (0, sep_pos); 223 std::string pat_str = file.substr (0, sep_pos);
170 std::string file_str = (sep_pos != std::string::npos) 224 std::string file_str = (sep_pos != std::string::npos)
171 ? file.substr (sep_pos) : ""; 225 ? file.substr (sep_pos) : "";
172 226
173 // Original pattern ends with "." or "..". Take it as we have it.
174 if (pat_str.empty ())
175 {
176 if (is_trailing_file_sep)
177 pat_str = sys::file_ops::dir_sep_char ();
178 dirlist.push_back (sys::file_ops::concat (dir, pat) + pat_str);
179 return;
180 }
181
182 // call this function recursively with next path component in PAT 227 // call this function recursively with next path component in PAT
183 find_files (dirlist, sys::file_ops::concat (dir, pat), 228 find_files (dirlist, sys::file_ops::concat (dir, found_dir),
184 pat_str, file_str); 229 pat_str, file_str);
185 return; 230 }
186 } 231 }
187 232 while (FindNextFileW (h_find, &ffd) != 0);
188 // find first file in directory that matches pattern in PAT 233 }
189 std::wstring wpat = u8_to_wstring (sys::file_ops::concat (dir, pat)); 234
190 _WIN32_FIND_DATAW ffd; 235 #endif
191 HANDLE h_find = FindFirstFileW (wpat.c_str (), &ffd); 236
192 // ignore any error 237 // Glob like Windows "dir". Treat only * and ? as wildcards,
193 if (h_find == INVALID_HANDLE_VALUE) 238 // and "*.*" matches filenames even if they do not contain ".".
194 return; 239 string_vector
195 240 windows_glob (const string_vector& pat)
196 unwind_action close_h_find ([=] () { FindClose (h_find); }); 241 {
197 242 string_vector retval;
198 // find all files that match pattern 243
199 do 244 int npat = pat.numel ();
200 { 245
201 // must be directory if pattern continues 246 #if defined (OCTAVE_USE_WINDOWS_API)
202 if (! (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 247
203 && (! file.empty () || is_trailing_file_sep)) 248 std::list<std::string> dirlist;
204 continue; 249
205 250 for (int i = 0; i < npat; i++)
206 std::string found_dir = u8_from_wstring (ffd.cFileName); 251 {
207 252 std::string xpat = pat(i);
208 if (file.empty ()) 253 if (xpat.empty ())
209 { 254 continue;
210 // Don't include "." and ".." in matches. 255
211 if (found_dir.compare (".") && found_dir.compare ("..")) 256 std::string dir = "";
257
258 // separate component until first file separator
259 std::size_t sep_pos
260 = xpat.find_first_of (sys::file_ops::dir_sep_chars ());
261
262 // handle UNC paths
263 if (sep_pos == 0 && xpat.length () > 1
264 && sys::file_ops::is_dir_sep (xpat[1]))
265 {
266 // start pattern with a file, i.e., "\\SERVER\share\file"
267 sep_pos = xpat.find_first_of (sys::file_ops::dir_sep_chars (), 2);
268 if (sep_pos != std::string::npos)
269 sep_pos = xpat.find_first_of (sys::file_ops::dir_sep_chars (),
270 sep_pos + 1);
271 if (sep_pos != std::string::npos)
272 {
273 dir = xpat.substr(0, sep_pos);
274 xpat = xpat.substr (sep_pos+1);
275 sep_pos = xpat.find_first_of (sys::file_ops::dir_sep_chars ());
276 }
277 }
278
279 std::string file = (sep_pos != std::string::npos)
280 ? xpat.substr (sep_pos) : "";
281 xpat = xpat.substr (0, sep_pos);
282
283 if ((sep_pos == 2 || xpat.length () == 2) && xpat[1] == ':')
284 {
285 // include disc root with first file or folder
286
287 // remove leading file separators in path without disc root
288 while (file.length () > 1 && sys::file_ops::is_dir_sep (file[0]))
289 file = file.substr (1, std::string::npos);
290
291 sep_pos = file.find_first_of (sys::file_ops::dir_sep_chars ());
292 dir = xpat;
293 xpat = file.substr (0, sep_pos);
294 file = (sep_pos != std::string::npos)
295 ? file.substr (sep_pos) : "";
296 if (xpat.empty ())
297 {
298 // don't glob if input is only disc root
299 std::wstring wpat = u8_to_wstring (pat(i));
300 if (PathFileExistsW (wpat.c_str ()))
212 { 301 {
213 if (is_trailing_file_sep) 302 if (sys::file_ops::is_dir_sep (pat(i).back ()))
214 found_dir += sys::file_ops::dir_sep_char (); 303 dirlist.push_back (dir +
215 dirlist.push_back (sys::file_ops::concat (dir, found_dir)); 304 sys::file_ops::dir_sep_char ());
305 else
306 dirlist.push_back (dir);
216 } 307 }
217 } 308 continue;
218 else 309 }
219 { 310 }
220 // get next component of path (or file name) 311
221 std::size_t sep_pos 312 find_files (dirlist, dir, xpat, file);
222 = file.find_first_of (sys::file_ops::dir_sep_chars ());
223 std::string pat_str = file.substr (0, sep_pos);
224 std::string file_str = (sep_pos != std::string::npos)
225 ? file.substr (sep_pos) : "";
226
227 // call this function recursively with next path component in PAT
228 find_files (dirlist, sys::file_ops::concat (dir, found_dir),
229 pat_str, file_str);
230 }
231 }
232 while (FindNextFileW (h_find, &ffd) != 0);
233 } 313 }
234 314
235 #endif 315 retval = string_vector (dirlist);
236 316
237 // Glob like Windows "dir". Treat only * and ? as wildcards, 317 #else
238 // and "*.*" matches filenames even if they do not contain ".". 318
239 string_vector 319 int k = 0;
240 windows_glob (const string_vector& pat) 320
321 void *glob_info = octave_create_glob_info_struct ();
322
323 unwind_action cleanup_glob_info_struct
324 ([=] () { octave_destroy_glob_info_struct (glob_info); });
325
326 for (int i = 0; i < npat; i++)
241 { 327 {
242 string_vector retval; 328 std::string xpat = pat(i);
243 329
244 int npat = pat.numel (); 330 if (! xpat.empty ())
245 331 {
246 #if defined (OCTAVE_USE_WINDOWS_API) 332 std::string escaped;
247 333 escaped.reserve (xpat.length ());
248 std::list<std::string> dirlist; 334
249 335 for (std::size_t j = 0; j < xpat.length (); j++)
250 for (int i = 0; i < npat; i++) 336 {
251 {
252 std::string xpat = pat(i);
253 if (xpat.empty ())
254 continue;
255
256 std::string dir = "";
257
258 // separate component until first file separator
259 std::size_t sep_pos
260 = xpat.find_first_of (sys::file_ops::dir_sep_chars ());
261
262 // handle UNC paths
263 if (sep_pos == 0 && xpat.length () > 1
264 && sys::file_ops::is_dir_sep (xpat[1]))
265 {
266 // start pattern with a file, i.e., "\\SERVER\share\file"
267 sep_pos = xpat.find_first_of (sys::file_ops::dir_sep_chars (), 2);
268 if (sep_pos != std::string::npos)
269 sep_pos = xpat.find_first_of (sys::file_ops::dir_sep_chars (),
270 sep_pos + 1);
271 if (sep_pos != std::string::npos)
272 {
273 dir = xpat.substr(0, sep_pos);
274 xpat = xpat.substr (sep_pos+1);
275 sep_pos = xpat.find_first_of (sys::file_ops::dir_sep_chars ());
276 }
277 }
278
279 std::string file = (sep_pos != std::string::npos)
280 ? xpat.substr (sep_pos) : "";
281 xpat = xpat.substr (0, sep_pos);
282
283 if ((sep_pos == 2 || xpat.length () == 2) && xpat[1] == ':')
284 {
285 // include disc root with first file or folder
286
287 // remove leading file separators in path without disc root
288 while (file.length () > 1 && sys::file_ops::is_dir_sep (file[0]))
289 file = file.substr (1, std::string::npos);
290
291 sep_pos = file.find_first_of (sys::file_ops::dir_sep_chars ());
292 dir = xpat;
293 xpat = file.substr (0, sep_pos);
294 file = (sep_pos != std::string::npos)
295 ? file.substr (sep_pos) : "";
296 if (xpat.empty ())
297 {
298 // don't glob if input is only disc root
299 std::wstring wpat = u8_to_wstring (pat(i));
300 if (PathFileExistsW (wpat.c_str ()))
301 {
302 if (sys::file_ops::is_dir_sep (pat(i).back ()))
303 dirlist.push_back (dir +
304 sys::file_ops::dir_sep_char ());
305 else
306 dirlist.push_back (dir);
307 }
308 continue;
309 }
310 }
311
312 find_files (dirlist, dir, xpat, file);
313 }
314
315 retval = string_vector (dirlist);
316
317 #else
318
319 int k = 0;
320
321 void *glob_info = octave_create_glob_info_struct ();
322
323 unwind_action cleanup_glob_info_struct
324 ([=] () { octave_destroy_glob_info_struct (glob_info); });
325
326 for (int i = 0; i < npat; i++)
327 {
328 std::string xpat = pat(i);
329
330 if (! xpat.empty ())
331 {
332 std::string escaped;
333 escaped.reserve (xpat.length ());
334
335 for (std::size_t j = 0; j < xpat.length (); j++)
336 {
337 # if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \ 337 # if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \
338 && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)) 338 && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))
339 if (xpat[j] == '\\') 339 if (xpat[j] == '\\')
340 escaped += '/'; 340 escaped += '/';
341 else 341 else
342 # endif 342 # endif
343 {
344 if (xpat[j] == ']' || xpat[j] == '[')
345 escaped += '\\';
346
347 escaped += xpat[j];
348 }
349 }
350
351 // Replace trailing "*.*" by "*".
352 int len = escaped.length ();
353 if (len >= 3 && escaped.substr (len - 3) == "*.*")
354 escaped = escaped.substr (0, len - 2);
355
356 int err = octave_glob_wrapper (escaped.c_str (),
357 octave_glob_nosort_wrapper (),
358 glob_info);
359
360 if (! err)
361 {
362 int n = octave_glob_num_matches (glob_info);
363
364 const char *const *matches
365 = octave_glob_match_list (glob_info);
366
367 // FIXME: we shouldn't have to check to see if
368 // a single match exists, but it seems that glob() won't
369 // check for us unless the pattern contains globbing
370 // characters. Hmm.
371
372 if (n > 1
373 || (n == 1
374 && single_match_exists (std::string (matches[0]))))
375 {
376 retval.resize (k + n);
377
378 for (int j = 0; j < n; j++)
343 { 379 {
344 if (xpat[j] == ']' || xpat[j] == '[') 380 std::string tmp = matches[j];
345 escaped += '\\'; 381
346 382 std::string unescaped;
347 escaped += xpat[j]; 383 unescaped.reserve (tmp.length ());
384
385 for (std::size_t m = 0; m < tmp.length (); m++)
386 {
387 # if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \
388 && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))
389 if (tmp[m] == '/')
390 unescaped += '\\';
391 else
392 # endif
393 {
394 if (tmp[m] == '\\'
395 && ++m == tmp.length ())
396 break;
397
398 unescaped += tmp[m];
399 }
400 }
401
402 retval[k++] = unescaped;
348 } 403 }
349 } 404 }
350 405
351 // Replace trailing "*.*" by "*". 406 octave_globfree_wrapper (glob_info);
352 int len = escaped.length (); 407 }
353 if (len >= 3 && escaped.substr (len - 3) == "*.*") 408 }
354 escaped = escaped.substr (0, len - 2);
355
356 int err = octave_glob_wrapper (escaped.c_str (),
357 octave_glob_nosort_wrapper (),
358 glob_info);
359
360 if (! err)
361 {
362 int n = octave_glob_num_matches (glob_info);
363
364 const char * const *matches
365 = octave_glob_match_list (glob_info);
366
367 // FIXME: we shouldn't have to check to see if
368 // a single match exists, but it seems that glob() won't
369 // check for us unless the pattern contains globbing
370 // characters. Hmm.
371
372 if (n > 1
373 || (n == 1
374 && single_match_exists (std::string (matches[0]))))
375 {
376 retval.resize (k + n);
377
378 for (int j = 0; j < n; j++)
379 {
380 std::string tmp = matches[j];
381
382 std::string unescaped;
383 unescaped.reserve (tmp.length ());
384
385 for (std::size_t m = 0; m < tmp.length (); m++)
386 {
387 # if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \
388 && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))
389 if (tmp[m] == '/')
390 unescaped += '\\';
391 else
392 # endif
393 {
394 if (tmp[m] == '\\'
395 && ++m == tmp.length ())
396 break;
397
398 unescaped += tmp[m];
399 }
400 }
401
402 retval[k++] = unescaped;
403 }
404 }
405
406 octave_globfree_wrapper (glob_info);
407 }
408 }
409 }
410 #endif
411
412 return retval.sort ();
413 } 409 }
410 #endif
411
412 return retval.sort ();
413 }
414 414
415 OCTAVE_END_NAMESPACE(sys) 415 OCTAVE_END_NAMESPACE(sys)
416 OCTAVE_END_NAMESPACE(octave) 416 OCTAVE_END_NAMESPACE(octave)