GRASS GIS 8 Programmer's Manual 8.4.1(2025)-45ca3179ab
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 * (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 char *buf;
23 size_t len;
24 size_t alloc;
25};
26
27static void init(struct buffer *buf)
28{
29 buf->buf = NULL;
30 buf->len = 0;
31 buf->alloc = 0;
32}
33
34static 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
44static void fini(struct buffer *buf)
45{
46 G_free(buf->buf);
47}
48
49static 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
74static 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
144static 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
151void *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
171void *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
190void 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 G_free(void *buf)
Free allocated memory.
Definition alloc.c:150
void init(double work[])
Definition as177.c:61
#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:66
void G_set_ls_exclude_filter(ls_filter_func *func, void *closure)
Definition ls.c:72