GRASS 8 Programmer's Manual 8.6.0dev(2026)-4bb960b182
Loading...
Searching...
No Matches
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 * SPDX-FileCopyrightText: 2010 Glynn Clements
7 * SPDX-FileCopyrightText: GRASS Development Team
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 *
10 * \author Original author Glynn Clements
11 */
12
13#include <grass/config.h>
14#include <grass/gis.h>
15#ifdef HAVE_REGEX_H
16#include <regex.h>
17#endif
18
19#ifdef HAVE_PCRE_H
20#include <string.h>
21#include <pcre.h>
22#endif
23
24struct buffer {
25 char *buf;
26 size_t len;
27 size_t alloc;
28};
29
30static void init(struct buffer *buf)
31{
32 buf->buf = NULL;
33 buf->len = 0;
34 buf->alloc = 0;
35}
36
37static void add(struct buffer *buf, char c)
38{
39 if (buf->len >= buf->alloc) {
40 buf->alloc += 50;
41 buf->buf = G_realloc(buf->buf, buf->alloc);
42 }
43
44 buf->buf[buf->len++] = c;
45}
46
47static void fini(struct buffer *buf)
48{
49 G_free(buf->buf);
50}
51
52static const char *do_set(struct buffer *buf, const char *p)
53{
54 add(buf, '[');
55
56 if (*p == '!') {
57 add(buf, '^');
58 p++;
59 }
60
61 if (*p == ']') {
62 add(buf, ']');
63 p++;
64 }
65
66 for (; *p && *p != ']'; p++)
67 add(buf, *p);
68
69 if (!*p)
70 return NULL;
71
72 add(buf, ']');
73
74 return p;
75}
76
77static int wc2regex(struct buffer *buf, const char *pat)
78{
79 const char *p;
80 int in_brace = 0;
81
82 init(buf);
83
84 add(buf, '^');
85
86 for (p = pat; p && *p; p++) {
87 switch (*p) {
88 case '\\':
89 add(buf, '\\');
90 if (!*++p)
91 return 0;
92 add(buf, *p);
93 break;
94 case '.':
95 case '|':
96 case '(':
97 case ')':
98 case '+':
99 add(buf, '\\');
100 add(buf, *p);
101 break;
102 case '*':
103 add(buf, '.');
104 add(buf, '*');
105 break;
106 case '?':
107 add(buf, '.');
108 break;
109 case '{':
110 in_brace++;
111 add(buf, '(');
112 break;
113 case '}':
114 if (!in_brace)
115 return 0;
116 in_brace--;
117 add(buf, ')');
118 break;
119 case ',':
120 if (in_brace)
121 add(buf, '|');
122 else
123 add(buf, ',');
124 break;
125 case '[':
126 if (!(p = do_set(buf, p)))
127 return 0;
128 break;
129 default:
130 add(buf, *p);
131 break;
132 }
133 }
134
135 if (!p)
136 return 0;
137
138 if (in_brace)
139 return 0;
140
141 add(buf, '$');
142 add(buf, '\0');
143
144 return 1;
145}
146
147static int re_filter(const char *filename, void *closure)
148{
149#ifdef HAVE_REGEX_H
150 regex_t *regex = closure;
151
152 return filename[0] != '.' && regexec(regex, filename, 0, NULL, 0) == 0;
153#endif
154#ifdef HAVE_PCRE_H
155 const char *pcreErrorStr;
157 int pcreExecRet;
158 pcre *pcre_regex = closure;
159
160 /* Optimize the regex */
163 strlen(filename), /* length of string */
164 0, /* Start looking at this point */
165 0, /* OPTIONS */
166 NULL, 0); /* Length of subStrVec */
167
168 return filename[0] != '.' && pcreExecRet == 0;
169#endif
170}
171
172void *G_ls_regex_filter(const char *pat, int exclude, int extended,
173 int ignorecase)
174{
175#ifdef HAVE_REGEX_H
176 regex_t *regex = G_malloc(sizeof(regex_t));
177
178 if (regcomp(regex, pat,
180 (ignorecase ? REG_ICASE : 0)) != 0) {
181 G_free(regex);
182 return NULL;
183 }
184
185 if (exclude)
186 G_set_ls_exclude_filter(re_filter, regex);
187 else
188 G_set_ls_filter(re_filter, regex);
189
190 return regex;
191#endif
192
193#ifdef HAVE_PCRE_H
195 const char *pcreErrorStr;
196 int pcreErrorOffset;
197
198 /* First, the regex string must be compiled */
200 /*
201 if (regcomp(regex, pat, REG_NOSUB |
202 (extended ? REG_EXTENDED : 0) |
203 (ignorecase ? REG_ICASE : 0)) != 0) {
204 pcre_free(pcre_regex);
205 return NULL;
206 }
207 */
208 if (exclude)
210 else
211 G_set_ls_filter(re_filter, pcre_regex);
212
213 /* First, the regex string must be compiled */
215 /*
216 if (regcomp(regex, pat, REG_NOSUB |
217 (extended ? REG_EXTENDED : 0) |
218 (ignorecase ? REG_ICASE : 0)) != 0) {
219 pcre_free(pcre_regex);
220 return NULL;
221 }
222 */
223 if (exclude)
225 else
226 G_set_ls_filter(re_filter, pcre_regex);
227
228 return pcre_regex;
229#endif
230}
231
232void *G_ls_glob_filter(const char *pat, int exclude, int ignorecase)
233{
234 struct buffer buf;
235
236#ifdef HAVE_REGEX_H
237 regex_t *regex;
238#endif
239#ifdef HAVE_PCRE_H
241#endif
242
243 init(&buf);
244
245 if (!wc2regex(&buf, pat)) {
246 fini(&buf);
247 return NULL;
248 }
249#ifdef HAVE_REGEX_H
251#endif
252#ifdef HAVE_PCRE_H
254#endif
255
256 fini(&buf);
257
258#ifdef HAVE_REGEX_H
259 return regex;
260#endif
261#ifdef HAVE_PCRE_H
262 return pcre_regex;
263#endif
264}
265
267{
268 if (!regex)
269 return;
270#ifdef HAVE_REGEX_H
271 regfree(regex);
272#endif
273#ifdef HAVE_PCRE_H
275#endif
276}
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:145
#define G_realloc(p, n)
Definition defs/gis.h:138
#define G_malloc(n)
Definition defs/gis.h:136
void G_set_ls_exclude_filter(int(*)(const char *, void *), void *)
void G_set_ls_filter(int(*)(const char *, void *), void *)
void * G_ls_regex_filter(const char *pat, int exclude, int extended, int ignorecase)
Definition ls_filter.c:172
void G_free_ls_filter(void *regex)
Definition ls_filter.c:266
void * G_ls_glob_filter(const char *pat, int exclude, int ignorecase)
Definition ls_filter.c:232