GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
oct-glob.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2010-2013 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #include <algorithm>
28 #include <string>
29 
30 #include <fnmatch.h>
31 #include <glob.h>
32 
33 #include "oct-glob.h"
34 #include "file-stat.h"
35 
36 // These functions are defined here and not in glob_match.cc so that we
37 // can include the glob.h file from gnulib, which defines glob to
38 // be rpl_glob. If we include glob.h in glob_match.cc, then it
39 // transforms the glob_match::glob function to be glob_match::rpl_glob,
40 // which is not what we want...
41 
42 static bool
43 single_match_exists (const std::string& file)
44 {
45  file_stat s (file);
46 
47  return s.exists ();
48 }
49 
50 bool
51 octave_fnmatch (const string_vector& pat, const std::string& str,
52  int fnmatch_flags)
53 {
54  int npat = pat.length ();
55 
56  const char *cstr = str.c_str ();
57 
58  for (int i = 0; i < npat; i++)
59  if (fnmatch (pat(i).c_str (), cstr, fnmatch_flags) != FNM_NOMATCH)
60  return true;
61 
62  return false;
63 }
64 
67 {
68  string_vector retval;
69 
70  int npat = pat.length ();
71 
72  int k = 0;
73 
74  for (int i = 0; i < npat; i++)
75  {
76  std::string xpat = pat(i);
77 
78  if (! xpat.empty ())
79  {
80  glob_t glob_info;
81 
82 #if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \
83  && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)
84  std::replace_if (xpat.begin (), xpat.end (),
85  std::bind2nd (std::equal_to<char> (), '\\'),
86  '/');
87 #endif
88 
89  int err = gnulib::glob (xpat.c_str (), GLOB_NOSORT, 0, &glob_info);
90 
91  if (! err)
92  {
93  int n = glob_info.gl_pathc;
94 
95  const char * const *matches = glob_info.gl_pathv;
96 
97  // FIXME: we shouldn't have to check to see if
98  // a single match exists, but it seems that glob() won't
99  // check for us unless the pattern contains globbing
100  // characters. Hmm.
101 
102  if (n > 1
103  || (n == 1
104  && single_match_exists (std::string (matches[0]))))
105  {
106  retval.resize (k+n);
107 
108  for (int j = 0; j < n; j++)
109  {
110  std::string tmp = matches[j];
111 
112 #if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \
113  && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)
114  std::replace_if (tmp.begin (), tmp.end (),
115  std::bind2nd (std::equal_to<char> (),
116  '/'),
117  '\\');
118 #endif
119 
120  retval[k++] = tmp;
121  }
122  }
123 
124  gnulib::globfree (&glob_info);
125  }
126  }
127  }
128 
129  return retval.sort ();
130 }