LibC: Implement fnmatch
This commit is contained in:
parent
af0bca74e4
commit
c96c264801
|
@ -10,6 +10,7 @@ set(LIBC_SOURCES
|
|||
errno.cpp
|
||||
fcntl.cpp
|
||||
fenv.cpp
|
||||
fnmatch.cpp
|
||||
ftw.cpp
|
||||
grp.cpp
|
||||
ifaddrs.cpp
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
#include <fnmatch.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
static int fnmatch_impl(const char* pattern, const char* string, int flags, bool leading)
|
||||
{
|
||||
while (*pattern)
|
||||
{
|
||||
if ((flags & FNM_PERIOD) && leading && *string == '.' && *pattern != '.')
|
||||
return FNM_NOMATCH;
|
||||
leading = false;
|
||||
|
||||
switch (*pattern)
|
||||
{
|
||||
case '*':
|
||||
{
|
||||
const char* ptr = strchrnul(string, (flags & FNM_PATHNAME) ? '/' : '0');
|
||||
while (ptr >= string)
|
||||
if (fnmatch_impl(pattern + 1, ptr--, flags, false) == 0)
|
||||
return 0;
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
case '[':
|
||||
{
|
||||
if (strchr(pattern, ']') == nullptr)
|
||||
break;
|
||||
pattern++;
|
||||
|
||||
const bool negate = (*pattern == '!');
|
||||
if (negate)
|
||||
pattern++;
|
||||
|
||||
uint8_t ch;
|
||||
uint32_t bitmap[0x100 / 8] {};
|
||||
while ((ch = *pattern++) != ']')
|
||||
bitmap[ch / 32] |= 1 << (ch % 32);
|
||||
|
||||
ch = *string++;
|
||||
if (!!(bitmap[ch / 32] & (1 << (ch % 32))) == negate)
|
||||
return FNM_NOMATCH;
|
||||
|
||||
continue;
|
||||
}
|
||||
case '?':
|
||||
{
|
||||
if (*string == '\0')
|
||||
return FNM_NOMATCH;
|
||||
if ((flags & FNM_PATHNAME) && *string == '/')
|
||||
return FNM_NOMATCH;
|
||||
pattern++;
|
||||
string++;
|
||||
continue;
|
||||
}
|
||||
case '\\':
|
||||
{
|
||||
if (!(flags & FNM_NOESCAPE))
|
||||
pattern++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (*pattern == '\0')
|
||||
break;
|
||||
|
||||
if (*pattern != *string)
|
||||
return FNM_NOMATCH;
|
||||
if ((flags & FNM_PATHNAME) && *string == '/')
|
||||
leading = true;
|
||||
pattern++;
|
||||
string++;
|
||||
}
|
||||
|
||||
return *string ? FNM_NOMATCH : 0;
|
||||
}
|
||||
|
||||
int fnmatch(const char* pattern, const char* string, int flags)
|
||||
{
|
||||
return fnmatch_impl(pattern, string, flags, true);
|
||||
}
|
Loading…
Reference in New Issue