mirror of
https://github.com/MeshEnvy/lobbs.git
synced 2026-10-31 02:11:59 +01:00
111 lines
2.7 KiB
C++
111 lines
2.7 KiB
C++
#include <lofs/Glob.h>
|
|
#include <lofs/LoFS.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
bool lobfsGlobHasMeta(const char *s)
|
|
{
|
|
for (; s && *s; s++) {
|
|
if (*s == '*' || *s == '?')
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool lobfsGlobMatch(const char *pat, const char *str)
|
|
{
|
|
if (!*pat)
|
|
return !*str;
|
|
if (*pat == '*') {
|
|
if (!pat[1])
|
|
return true;
|
|
for (; *str; str++) {
|
|
if (lobfsGlobMatch(pat + 1, str))
|
|
return true;
|
|
}
|
|
return lobfsGlobMatch(pat + 1, str);
|
|
}
|
|
if (*pat == '?') {
|
|
if (!*str)
|
|
return false;
|
|
return lobfsGlobMatch(pat + 1, str + 1);
|
|
}
|
|
if (*pat != *str)
|
|
return false;
|
|
return lobfsGlobMatch(pat + 1, str + 1);
|
|
}
|
|
|
|
bool lobfsGlobBeforeLastName(const char *path)
|
|
{
|
|
if (!path)
|
|
return false;
|
|
const char *lastSlash = strrchr(path, '/');
|
|
const char *end = lastSlash ? lastSlash : path;
|
|
for (const char *p = path; p < end; p++) {
|
|
if (*p == '*' || *p == '?')
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool lobfsGlobLastComponentHasMeta(const char *path)
|
|
{
|
|
if (!path)
|
|
return false;
|
|
const char *lastSlash = strrchr(path, '/');
|
|
const char *last = lastSlash ? lastSlash + 1 : path;
|
|
return lobfsGlobHasMeta(last);
|
|
}
|
|
|
|
struct LobfsGlobOneFile {
|
|
const char *pattern;
|
|
const char *dirPath;
|
|
char *out;
|
|
size_t outCap;
|
|
int count;
|
|
};
|
|
|
|
static bool lobfsGlobOneFileCb(void *ctx, const char *basename, bool isDirectory, uint32_t size)
|
|
{
|
|
(void)size;
|
|
if (isDirectory)
|
|
return true;
|
|
auto *mc = (LobfsGlobOneFile *)ctx;
|
|
if (!lobfsGlobMatch(mc->pattern, basename))
|
|
return true;
|
|
if (mc->count == 0)
|
|
snprintf(mc->out, mc->outCap, "%s/%s", mc->dirPath, basename);
|
|
mc->count++;
|
|
return true;
|
|
}
|
|
|
|
LobfsGlobResolve lobfsGlobResolveOneFile(char *path, char *out, size_t outCap)
|
|
{
|
|
if (lobfsGlobBeforeLastName(path))
|
|
return LobfsGlobResolve::GlobBeforeLast;
|
|
|
|
if (!lobfsGlobLastComponentHasMeta(path)) {
|
|
strncpy(out, path, outCap - 1);
|
|
out[outCap - 1] = '\0';
|
|
return LobfsGlobResolve::Ok;
|
|
}
|
|
|
|
char *lastSlash = strrchr(path, '/');
|
|
LobfsGlobOneFile m{};
|
|
m.pattern = lastSlash + 1;
|
|
m.dirPath = lastSlash == path ? "/" : path;
|
|
m.out = out;
|
|
m.outCap = outCap;
|
|
*lastSlash = '\0';
|
|
bool listed = LoFS::list(m.dirPath, &m, lobfsGlobOneFileCb);
|
|
*lastSlash = '/';
|
|
|
|
if (!listed)
|
|
return LobfsGlobResolve::NoDir;
|
|
if (m.count == 0)
|
|
return LobfsGlobResolve::NoMatch;
|
|
if (m.count > 1)
|
|
return LobfsGlobResolve::ManyMatches;
|
|
return LobfsGlobResolve::Ok;
|
|
}
|