Skip to content

Commit e0eb14a

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 bf0e0b3 commit e0eb14a

File tree

1 file changed

+161
-0
lines changed

1 file changed

+161
-0
lines changed

lib/posix/c_lib_ext/fnmatch.c

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

@@ -60,6 +191,24 @@ static inline int foldcase(int ch, int flags)
60191

61192
#define FOLDCASE(ch, flags) foldcase((unsigned char)(ch), (flags))
62193

194+
static bool match_posix_class(const char **pattern, int test)
195+
{
196+
enum fnm_char_class cc;
197+
198+
const char *p = *pattern;
199+
size_t remaining = strlen(p);
200+
201+
if (!fnm_cc_is_valid(p, remaining, &cc))
202+
return false;
203+
204+
/* move pattern pointer past ":]" */
205+
const char *end = strstr(p, ":]");
206+
if (end)
207+
*pattern = end + 2;
208+
209+
return fnm_cc_match(test, cc);
210+
}
211+
63212
static const char *rangematch(const char *pattern, int test, int flags)
64213
{
65214
bool negate, ok, need;
@@ -99,6 +248,18 @@ static const char *rangematch(const char *pattern, int test, int flags)
99248
return NULL;
100249
}
101250

251+
if (c == '[' && *pattern == ':') {
252+
if (match_posix_class(&pattern, test)) {
253+
ok = true;
254+
continue;
255+
} else {
256+
// skip over class if unrecognized
257+
while (*pattern && !(*pattern == ':' && *(pattern+1) == ']')) pattern++;
258+
if (*pattern) pattern += 2;
259+
continue;
260+
}
261+
}
262+
102263
if (*pattern == '-') {
103264
c2 = FOLDCASE(*(pattern + 1), flags);
104265
if (c2 != EOS && c2 != ']') {

0 commit comments

Comments
 (0)