2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2004 Net Integration Technologies, Inc.
5 * Implementation of globbing support through WvRegex
9 WvGlob::WvGlob() : WvRegex()
13 WvGlob::WvGlob(WvStringParm glob
) : WvRegex()
18 bool WvGlob::set(WvStringParm glob
)
21 WvString regex
= glob_to_regex(glob
, &errstr
);
23 WvErrorBase::seterr(errstr
);
26 else WvErrorBase::seterr("Failed to convert glob pattern to regex");
30 const bool WvGlob::normal_quit_chars
[256] = {
31 false, false, false, false, false, false, false, false,
32 false, false, false, false, false, false, false, false,
33 false, false, false, false, false, false, false, false,
34 false, false, false, false, false, false, false, false,
35 false, false, false, false, false, false, false, false,
36 false, false, false, false, false, false, false, false,
37 false, false, false, false, false, false, false, false,
38 false, false, false, false, false, false, false, false,
39 false, false, false, false, false, false, false, false,
40 false, false, false, false, false, false, false, false,
41 false, false, false, false, false, false, false, false,
42 false, false, false, false, false, false, false, false,
43 false, false, false, false, false, false, false, false,
44 false, false, false, false, false, false, false, false,
45 false, false, false, false, false, false, false, false,
46 false, false, false, false, false, false, false, false,
47 false, false, false, false, false, false, false, false,
48 false, false, false, false, false, false, false, false,
49 false, false, false, false, false, false, false, false,
50 false, false, false, false, false, false, false, false,
51 false, false, false, false, false, false, false, false,
52 false, false, false, false, false, false, false, false,
53 false, false, false, false, false, false, false, false,
54 false, false, false, false, false, false, false, false,
55 false, false, false, false, false, false, false, false,
56 false, false, false, false, false, false, false, false,
57 false, false, false, false, false, false, false, false,
58 false, false, false, false, false, false, false, false,
59 false, false, false, false, false, false, false, false,
60 false, false, false, false, false, false, false, false,
61 false, false, false, false, false, false, false, false,
62 false, false, false, false, false, false, false, false
64 const bool WvGlob::brace_quit_chars
[256] = {
65 false, false, false, false, false, false, false, false,
66 false, false, false, false, false, false, false, false,
67 false, false, false, false, false, false, false, false,
68 false, false, false, false, false, false, false, false,
69 false, false, false, false, false, false, false, false,
70 false, false, false, false, true /* , */, false, false, false,
71 false, false, false, false, false, false, false, false,
72 false, false, false, false, false, false, false, false,
73 false, false, false, false, false, false, false, false,
74 false, false, false, false, false, false, false, false,
75 false, false, false, false, false, false, false, false,
76 false, false, false, false, false, false, false, false,
77 false, false, false, false, false, false, false, false,
78 false, false, false, false, false, false, false, false,
79 false, false, false, false, false, false, false, false,
80 false, false, false, false, false, true /* } */, false, false,
81 false, false, false, false, false, false, false, false,
82 false, false, false, false, false, false, false, false,
83 false, false, false, false, false, false, false, false,
84 false, false, false, false, false, false, false, false,
85 false, false, false, false, false, false, false, false,
86 false, false, false, false, false, false, false, false,
87 false, false, false, false, false, false, false, false,
88 false, false, false, false, false, false, false, false,
89 false, false, false, false, false, false, false, false,
90 false, false, false, false, false, false, false, false,
91 false, false, false, false, false, false, false, false,
92 false, false, false, false, false, false, false, false,
93 false, false, false, false, false, false, false, false,
94 false, false, false, false, false, false, false, false,
95 false, false, false, false, false, false, false, false,
96 false, false, false, false, false, false, false, false
102 // - If / is part of a range it will not be excluded in the resulting regex
103 // eg. fred[.-0]joe will match fred/joe (this violates glob(7))
104 // However, explcit / in bracket expression results in error.
106 WvString
WvGlob::glob_to_regex(const char *src
, size_t &src_used
,
107 char *dst
, size_t &dst_used
, const bool quit_chars
[256])
109 enum { NORMAL
, BACKSLASH
, BRACKET
, BRACKET_FIRST
} state
= NORMAL
;
112 bool quit_now
= false;
113 while (!quit_now
&& src
[src_used
])
118 if (quit_chars
[(unsigned char)src
[src_used
]])
124 switch (src
[src_used
])
131 if (src
[src_used
+1] == '^' && src
[src_used
+2] == ']')
133 // Get rid of degenerate case:
135 if (dst
) dst
[dst_used
] = '\\'; ++dst_used
;
136 if (dst
) dst
[dst_used
] = '^'; ++dst_used
;
140 if (dst
) dst
[dst_used
] = '('; ++dst_used
;
141 state
= BRACKET_FIRST
;
146 if (dst
) dst
[dst_used
] = '('; ++dst_used
;
147 if (dst
) dst
[dst_used
] = '['; ++dst_used
;
148 if (dst
) dst
[dst_used
] = '^'; ++dst_used
;
149 if (dst
) dst
[dst_used
] = '/'; ++dst_used
;
150 if (dst
) dst
[dst_used
] = ']'; ++dst_used
;
151 if (dst
) dst
[dst_used
] = '*'; ++dst_used
;
152 if (dst
) dst
[dst_used
] = ')'; ++dst_used
;
156 if (dst
) dst
[dst_used
] = '('; ++dst_used
;
157 if (dst
) dst
[dst_used
] = '['; ++dst_used
;
158 if (dst
) dst
[dst_used
] = '^'; ++dst_used
;
159 if (dst
) dst
[dst_used
] = '/'; ++dst_used
;
160 if (dst
) dst
[dst_used
] = ']'; ++dst_used
;
161 if (dst
) dst
[dst_used
] = ')'; ++dst_used
;
165 if (dst
) dst
[dst_used
] = '('; ++dst_used
;
169 size_t sub_src_used
, sub_dst_used
;
172 glob_to_regex(&src
[src_used
], sub_src_used
,
173 dst
? &dst
[dst_used
]: NULL
, sub_dst_used
,
175 if (errstr
) return errstr
;
177 src_used
+= sub_src_used
;
178 dst_used
+= sub_dst_used
;
180 if (src
[src_used
] == '}')
182 else if (src
[src_used
] != ',')
183 return WvString("Unfinished brace expression (index %s)", src_used
);
184 if (dst
) dst
[dst_used
] = '|'; ++dst_used
;
187 if (dst
) dst
[dst_used
] = ')'; ++dst_used
;
197 if (dst
) dst
[dst_used
] = '\\'; ++dst_used
;
198 if (dst
) dst
[dst_used
] = src
[src_used
]; ++dst_used
;
202 if (dst
) dst
[dst_used
] = src
[src_used
]; ++dst_used
;
208 switch (src
[src_used
])
222 if (dst
) dst
[dst_used
] = '\\'; ++dst_used
;
225 if (dst
) dst
[dst_used
] = src
[src_used
]; ++dst_used
;
233 switch (src
[src_used
])
236 if (dst
) dst
[dst_used
] = '['; ++dst_used
;
237 if (dst
) dst
[dst_used
] = '^'; ++dst_used
;
241 if (dst
) dst
[dst_used
] = '\\'; ++dst_used
;
242 if (dst
) dst
[dst_used
] = '^'; ++dst_used
;
243 if (dst
) dst
[dst_used
] = '|'; ++dst_used
;
244 if (dst
) dst
[dst_used
] = '['; ++dst_used
;
248 return WvString("Slash not allowed in bracket expression (index %s)", src_used
);
251 if (dst
) dst
[dst_used
] = '['; ++dst_used
;
252 if (dst
) dst
[dst_used
] = src
[src_used
]; ++dst_used
;
259 switch (src
[src_used
])
262 if (dst
) dst
[dst_used
] = ']'; ++dst_used
;
263 if (dst
) dst
[dst_used
] = ')'; ++dst_used
;
268 return WvString("Slash not allowed in bracket expression (index %s)", src_used
);
271 if (dst
) dst
[dst_used
] = src
[src_used
]; ++dst_used
;
277 if (!quit_now
) ++src_used
;
280 if (state
== BRACKET
|| state
== BRACKET_FIRST
)
281 return WvString("Unfinished bracket expression (index %s)", src_used
);
282 else if (state
== BACKSLASH
)
283 return WvString("Unfinished backslash expression (index %s)", src_used
);
284 else return WvString::null
;
287 WvString
WvGlob::glob_to_regex(WvStringParm glob
, WvString
*errstr
)
291 if (errstr
) *errstr
= WvString("Glob is NULL");
292 return WvString::null
;
295 size_t src_used
, dst_used
;
296 WvString local_errstr
= glob_to_regex(glob
, src_used
, NULL
, dst_used
, normal_quit_chars
);
299 if (errstr
) *errstr
= local_errstr
;
300 return WvString::null
;
304 result
.setsize(1+dst_used
+1+1);
305 char *dst
= result
.edit();
307 local_errstr
= glob_to_regex(glob
, src_used
, dst
, dst_used
, normal_quit_chars
);
310 if (errstr
) *errstr
= local_errstr
;
311 return WvString::null
;