GRASS GIS 8 Programmer's Manual 8.2.0(2022)-exported
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
21struct buffer
22{
23 char *buf;
24 size_t len;
25 size_t alloc;
26};
27
28static void init(struct buffer *buf)
29{
30 buf->buf = NULL;
31 buf->len = 0;
32 buf->alloc = 0;
33}
34
35static void add(struct buffer *buf, char c)
36{
37 if (buf->len >= buf->alloc) {
38 buf->alloc += 50;
39 buf->buf = G_realloc(buf->buf, buf->alloc);
40 }
41
42 buf->buf[buf->len++] = c;
43}
44
45static void fini(struct buffer *buf)
46{
47 G_free(buf->buf);
48}
49
50static const char *do_set(struct buffer *buf, const char *p)
51{
52 add(buf, '[');
53
54 if (*p == '!') {
55 add(buf, '^');
56 p++;
57 }
58
59 if (*p == ']') {
60 add(buf, ']');
61 p++;
62 }
63
64 for (; *p && *p != ']'; p++)
65 add(buf, *p);
66
67 if (!*p)
68 return NULL;
69
70 add(buf, ']');
71
72 return p;
73}
74
75static int wc2regex(struct buffer *buf, const char *pat)
76{
77 const char *p;
78 int in_brace = 0;
79
80 init(buf);
81
82 add(buf, '^');
83
84 for (p = pat; p && *p; p++) {
85 switch (*p) {
86 case '\\':
87 add(buf, '\\');
88 if (!*++p)
89 return 0;
90 add(buf, *p);
91 break;
92 case '.':
93 case '|':
94 case '(':
95 case ')':
96 case '+':
97 add(buf, '\\');
98 add(buf, *p);
99 break;
100 case '*':
101 add(buf, '.');
102 add(buf, '*');
103 break;
104 case '?':
105 add(buf, '.');
106 break;
107 case '{':
108 in_brace++;
109 add(buf, '(');
110 break;
111 case '}':
112 if (!in_brace)
113 return 0;
114 in_brace--;
115 add(buf, ')');
116 break;
117 case ',':
118 if (in_brace)
119 add(buf, '|');
120 else
121 add(buf, ',');
122 break;
123 case '[':
124 if (!(p = do_set(buf, p)))
125 return 0;
126 break;
127 default:
128 add(buf, *p);
129 break;
130 }
131 }
132
133 if (!p)
134 return 0;
135
136 if (in_brace)
137 return 0;
138
139 add(buf, '$');
140 add(buf, '\0');
141
142 return 1;
143}
144
145static int re_filter(const char *filename, void *closure)
146{
147 regex_t *regex = closure;
148
149 return filename[0] != '.' && regexec(regex, filename, 0, NULL, 0) == 0;
150}
151
152void *G_ls_regex_filter(const char *pat, int exclude, int extended,
153 int ignorecase)
154{
155 regex_t *regex = G_malloc(sizeof(regex_t));
156
157 if (regcomp(regex, pat, REG_NOSUB |
158 (extended ? REG_EXTENDED : 0) |
159 (ignorecase ? REG_ICASE : 0)) != 0) {
160 G_free(regex);
161 return NULL;
162 }
163
164 if (exclude)
165 G_set_ls_exclude_filter(re_filter, regex);
166 else
167 G_set_ls_filter(re_filter, regex);
168
169 return regex;
170}
171
172void *G_ls_glob_filter(const char *pat, int exclude, int ignorecase)
173{
174 struct buffer buf;
175 regex_t *regex;
176
177 init(&buf);
178
179 if (!wc2regex(&buf, pat)) {
180 fini(&buf);
181 return NULL;
182 }
183
184 regex = G_ls_regex_filter(buf.buf, exclude, 1, ignorecase);
185
186 fini(&buf);
187
188 return regex;
189}
190
191void G_free_ls_filter(void *regex)
192{
193 if (!regex)
194 return;
195
196 regfree(regex);
197 G_free(regex);
198}
199
200#endif
201
void G_free(void *buf)
Free allocated memory.
Definition: alloc.c:149
void init(double work[])
Definition: as177.c:65
#define NULL
Definition: ccmath.h:32
void G_set_ls_filter(ls_filter_func *func, void *closure)
Sets a function and its complementary data for G_ls2 filtering.
Definition: ls.c:67
void G_set_ls_exclude_filter(ls_filter_func *func, void *closure)
Definition: ls.c:73