GRASS GIS 8 Programmer's Manual  8.4.0dev(2024)-112dd97adf
ls_filter.c
Go to the documentation of this file.
1 /*!
2  * \file lib/gis/ls_filter.c
3  *
4  * \brief GIS Library - Filename filter functions
5  *
6  * (C) 2010 by Glynn Clements and the GRASS Development Team
7  *
8  * This program is free software under the GNU General Public License
9  * (>=v2). Read the file COPYING that comes with GRASS for details.
10  *
11  * \author Original author Glynn Clements
12  */
13 
14 #include <grass/config.h>
15 #include <grass/gis.h>
16 
17 #ifdef HAVE_REGEX_H
18 
19 #include <regex.h>
20 
21 struct buffer {
22  char *buf;
23  size_t len;
24  size_t alloc;
25 };
26 
27 static void init(struct buffer *buf)
28 {
29  buf->buf = NULL;
30  buf->len = 0;
31  buf->alloc = 0;
32 }
33 
34 static void add(struct buffer *buf, char c)
35 {
36  if (buf->len >= buf->alloc) {
37  buf->alloc += 50;
38  buf->buf = G_realloc(buf->buf, buf->alloc);
39  }
40 
41  buf->buf[buf->len++] = c;
42 }
43 
44 static void fini(struct buffer *buf)
45 {
46  G_free(buf->buf);
47 }
48 
49 static const char *do_set(struct buffer *buf, const char *p)
50 {
51  add(buf, '[');
52 
53  if (*p == '!') {
54  add(buf, '^');
55  p++;
56  }
57 
58  if (*p == ']') {
59  add(buf, ']');
60  p++;
61  }
62 
63  for (; *p && *p != ']'; p++)
64  add(buf, *p);
65 
66  if (!*p)
67  return NULL;
68 
69  add(buf, ']');
70 
71  return p;
72 }
73 
74 static int wc2regex(struct buffer *buf, const char *pat)
75 {
76  const char *p;
77  int in_brace = 0;
78 
79  init(buf);
80 
81  add(buf, '^');
82 
83  for (p = pat; p && *p; p++) {
84  switch (*p) {
85  case '\\':
86  add(buf, '\\');
87  if (!*++p)
88  return 0;
89  add(buf, *p);
90  break;
91  case '.':
92  case '|':
93  case '(':
94  case ')':
95  case '+':
96  add(buf, '\\');
97  add(buf, *p);
98  break;
99  case '*':
100  add(buf, '.');
101  add(buf, '*');
102  break;
103  case '?':
104  add(buf, '.');
105  break;
106  case '{':
107  in_brace++;
108  add(buf, '(');
109  break;
110  case '}':
111  if (!in_brace)
112  return 0;
113  in_brace--;
114  add(buf, ')');
115  break;
116  case ',':
117  if (in_brace)
118  add(buf, '|');
119  else
120  add(buf, ',');
121  break;
122  case '[':
123  if (!(p = do_set(buf, p)))
124  return 0;
125  break;
126  default:
127  add(buf, *p);
128  break;
129  }
130  }
131 
132  if (!p)
133  return 0;
134 
135  if (in_brace)
136  return 0;
137 
138  add(buf, '$');
139  add(buf, '\0');
140 
141  return 1;
142 }
143 
144 static int re_filter(const char *filename, void *closure)
145 {
146  regex_t *regex = closure;
147 
148  return filename[0] != '.' && regexec(regex, filename, 0, NULL, 0) == 0;
149 }
150 
151 void *G_ls_regex_filter(const char *pat, int exclude, int extended,
152  int ignorecase)
153 {
154  regex_t *regex = G_malloc(sizeof(regex_t));
155 
156  if (regcomp(regex, pat,
157  REG_NOSUB | (extended ? REG_EXTENDED : 0) |
158  (ignorecase ? REG_ICASE : 0)) != 0) {
159  G_free(regex);
160  return NULL;
161  }
162 
163  if (exclude)
164  G_set_ls_exclude_filter(re_filter, regex);
165  else
166  G_set_ls_filter(re_filter, regex);
167 
168  return regex;
169 }
170 
171 void *G_ls_glob_filter(const char *pat, int exclude, int ignorecase)
172 {
173  struct buffer buf;
174  regex_t *regex;
175 
176  init(&buf);
177 
178  if (!wc2regex(&buf, pat)) {
179  fini(&buf);
180  return NULL;
181  }
182 
183  regex = G_ls_regex_filter(buf.buf, exclude, 1, ignorecase);
184 
185  fini(&buf);
186 
187  return regex;
188 }
189 
190 void G_free_ls_filter(void *regex)
191 {
192  if (!regex)
193  return;
194 
195  regfree(regex);
196  G_free(regex);
197 }
198 
199 #endif
void init(double work[])
Definition: as177.c:61
#define NULL
Definition: ccmath.h:32
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:150
#define G_realloc(p, n)
Definition: defs/gis.h:96
#define G_malloc(n)
Definition: defs/gis.h:94
void G_set_ls_exclude_filter(int(*)(const char *, void *), void *)
void G_set_ls_filter(int(*)(const char *, void *), void *)
void * G_ls_glob_filter(const char *pat, int exclude, int ignorecase)
Definition: ls_filter.c:171
void * G_ls_regex_filter(const char *pat, int exclude, int extended, int ignorecase)
Definition: ls_filter.c:151
void G_free_ls_filter(void *regex)
Definition: ls_filter.c:190