Skip to content

Commit 711b804

Browse files
committed
posix: c_lib_ext: fnmatch: add support for posix character classes
Implemented match_posix_class function that was needed to match the possible posix classes like alnum, alpha etc... Signed-off-by: Harun Spago <harun.spago.code@gmail.com>
1 parent 3cf7b20 commit 711b804

File tree

1 file changed

+170
-0
lines changed

1 file changed

+170
-0
lines changed

lib/posix/c_lib_ext/fnmatch.c

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,146 @@
4848

4949
#define EOS '\0'
5050

51+
#define MATCH_CLASS6(p,a,b,c,d,e,f,g) \
52+
((p)[0]==(a) && (p)[1]==(b) && (p)[2]==(c) && (p)[3]==(d) && (p)[4]==(e) && (p)[5]==(f) && (p)[6]==(g))
53+
54+
#define MATCH_CLASS7(p,a,b,c,d,e,f,g,h) \
55+
((p)[0]==(a) && (p)[1]==(b) && (p)[2]==(c) && (p)[3]==(d) && (p)[4]==(e) && (p)[5]==(f) && (p)[6]==(g) && (p)[7]==(h))
56+
57+
enum fnm_char_class {
58+
FNM_CC_ALNUM,
59+
FNM_CC_ALPHA,
60+
FNM_CC_BLANK,
61+
FNM_CC_CNTRL,
62+
FNM_CC_DIGIT,
63+
FNM_CC_GRAPH,
64+
FNM_CC_LOWER,
65+
FNM_CC_PRINT,
66+
FNM_CC_PUNCT,
67+
FNM_CC_SPACE,
68+
FNM_CC_UPPER,
69+
FNM_CC_XDIGIT,
70+
FNM_CC_INVALID,
71+
};
72+
73+
static bool fnm_cc_is_valid(const char *pattern, size_t psize, enum fnm_char_class *cc)
74+
{
75+
if (psize < 4 || *pattern != ':')
76+
return false;
77+
78+
pattern++; /* skip ':' */
79+
psize--;
80+
81+
/* Each class name ends with ":]" */
82+
switch (pattern[0]) {
83+
case 'a':
84+
if (MATCH_CLASS6(pattern,'a','l','n','u','m',':',']')) {
85+
*cc = FNM_CC_ALNUM;
86+
return true;
87+
}
88+
if (MATCH_CLASS6(pattern,'a','l','p','h','a',':',']')) {
89+
*cc = FNM_CC_ALPHA;
90+
return true;
91+
}
92+
break;
93+
94+
case 'b':
95+
if (MATCH_CLASS6(pattern,'b','l','a','n','k',':',']')) {
96+
*cc = FNM_CC_BLANK;
97+
return true;
98+
}
99+
break;
100+
101+
case 'c':
102+
if (MATCH_CLASS6(pattern,'c','n','t','r','l',':',']')) {
103+
*cc = FNM_CC_CNTRL;
104+
return true;
105+
}
106+
break;
107+
108+
case 'd':
109+
if (MATCH_CLASS6(pattern,'d','i','g','i','t',':',']')) {
110+
*cc = FNM_CC_DIGIT;
111+
return true;
112+
}
113+
break;
114+
115+
case 'g':
116+
if (MATCH_CLASS6(pattern,'g','r','a','p','h',':',']')) {
117+
*cc = FNM_CC_GRAPH;
118+
return true;
119+
}
120+
break;
121+
122+
case 'l':
123+
if (MATCH_CLASS6(pattern,'l','o','w','e','r',':',']')) {
124+
*cc = FNM_CC_LOWER;
125+
return true;
126+
}
127+
break;
128+
129+
case 'p':
130+
if (MATCH_CLASS6(pattern,'p','r','i','n','t',':',']')) {
131+
*cc = FNM_CC_PRINT;
132+
return true;
133+
}
134+
if (MATCH_CLASS6(pattern,'p','u','n','c','t',':',']')) {
135+
*cc = FNM_CC_PUNCT;
136+
return true;
137+
}
138+
break;
139+
140+
case 's':
141+
if (MATCH_CLASS6(pattern,'s','p','a','c','e',':',']')) {
142+
*cc = FNM_CC_SPACE;
143+
return true;
144+
}
145+
break;
146+
147+
case 'u':
148+
if (MATCH_CLASS6(pattern,'u','p','p','e','r',':',']')) {
149+
*cc = FNM_CC_UPPER;
150+
return true;
151+
}
152+
break;
153+
154+
case 'x':
155+
if (MATCH_CLASS7(pattern,'x','d','i','g','i','t',':',']')) {
156+
*cc = FNM_CC_XDIGIT;
157+
return true;
158+
}
159+
break;
160+
161+
default:
162+
break;
163+
}
164+
165+
return false;
166+
}
167+
168+
static inline int fnm_cc_match(int c, enum fnm_char_class cc)
169+
{
170+
switch (cc) {
171+
case FNM_CC_ALNUM: return isalnum(c);
172+
case FNM_CC_ALPHA: return isalpha(c);
173+
case FNM_CC_BLANK: return isblank(c);
174+
case FNM_CC_CNTRL: return iscntrl(c);
175+
case FNM_CC_DIGIT: return isdigit(c);
176+
case FNM_CC_GRAPH: return isgraph(c);
177+
case FNM_CC_LOWER: return islower(c);
178+
case FNM_CC_PRINT: return isprint(c);
179+
case FNM_CC_PUNCT: return ispunct(c);
180+
case FNM_CC_SPACE: return isspace(c);
181+
case FNM_CC_UPPER: return isupper(c);
182+
case FNM_CC_XDIGIT: return isxdigit(c);
183+
default:
184+
break;
185+
}
186+
187+
return 0;
188+
}
189+
190+
51191
static inline int foldcase(int ch, int flags)
52192
{
53193

@@ -60,6 +200,24 @@ static inline int foldcase(int ch, int flags)
60200

61201
#define FOLDCASE(ch, flags) foldcase((unsigned char)(ch), (flags))
62202

203+
static bool match_posix_class(const char **pattern, int test)
204+
{
205+
enum fnm_char_class cc;
206+
207+
const char *p = *pattern;
208+
size_t remaining = strlen(p);
209+
210+
if (!fnm_cc_is_valid(p, remaining, &cc))
211+
return false;
212+
213+
/* move pattern pointer past ":]" */
214+
const char *end = strstr(p, ":]");
215+
if (end)
216+
*pattern = end + 2;
217+
218+
return fnm_cc_match(test, cc);
219+
}
220+
63221
static const char *rangematch(const char *pattern, int test, int flags)
64222
{
65223
bool negate, ok, need;
@@ -99,6 +257,18 @@ static const char *rangematch(const char *pattern, int test, int flags)
99257
return NULL;
100258
}
101259

260+
if (c == '[' && *pattern == ':') {
261+
if (match_posix_class(&pattern, test)) {
262+
ok = true;
263+
continue;
264+
} else {
265+
// skip over class if unrecognized
266+
while (*pattern && !(*pattern == ':' && *(pattern+1) == ']')) pattern++;
267+
if (*pattern) pattern += 2;
268+
continue;
269+
}
270+
}
271+
102272
if (*pattern == '-') {
103273
c2 = FOLDCASE(*(pattern + 1), flags);
104274
if (c2 != EOS && c2 != ']') {

0 commit comments

Comments
 (0)