Skip to content

Commit

Permalink
Optimize: Use Unicode in file name pattern matching
Browse files Browse the repository at this point in the history
This does not perform any faster than the original, but it removes
the need to convert the path and pattern to UTF-8 before the matching.

Plus it's Unicode, so non-ASCII characters won't be a problem.
  • Loading branch information
skyjake committed Dec 5, 2012
1 parent 2052b16 commit b1a14dc
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 22 deletions.
22 changes: 14 additions & 8 deletions doomsday/engine/include/filesys/fs_util.h
Expand Up @@ -170,14 +170,6 @@ boolean F_TranslatePath(ddstring_t* dst, const ddstring_t* src);
*/
const char* F_PrettyPath(const char* path);

/**
* This is a case-insensitive test.
* I do hope this algorithm works like it should...
*
* @return @c true, if @a filePath matches the pattern.
*/
int F_MatchFileName(const char* filePath, const char* pattern);

/**
* Write the data associated with the specified lump index to @a fileName.
*
Expand Down Expand Up @@ -207,6 +199,20 @@ boolean F_Dump(void const* data, size_t size, char const* path);

#ifdef __cplusplus
} // extern "C"

#include <QChar>

/**
* Performs a case-insensitive pattern match. The pattern can contain
* wildcards.
*
* @param filePath Path to match.
* @param pattern Pattern with * and ? as wildcards.
*
* @return @c true, if @a filePath matches the pattern.
*/
bool F_MatchFileName(QChar const *filePath, QChar const *pattern);

#endif

#endif /// LIBDENG_FILESYS_UTIL_H
9 changes: 3 additions & 6 deletions doomsday/engine/src/filesys/fs_main.cpp
Expand Up @@ -804,7 +804,6 @@ int FS1::findAllPaths(String searchPattern, int flags, FS1::PathList& found)
}

de::Uri patternMap = de::Uri(searchPattern, RC_NULL);
QByteArray searchPatternUtf8 = searchPattern.toUtf8();

/*
* Check the Zip directory.
Expand All @@ -819,8 +818,7 @@ int FS1::findAllPaths(String searchPattern, int flags, FS1::PathList& found)
if(!(flags & SearchPath::NoDescend))
{
filePath = new String(lump.composePath());
QByteArray filePathUtf8 = filePath->toUtf8();
patternMatched = F_MatchFileName(filePathUtf8.constData(), searchPatternUtf8.constData());
patternMatched = F_MatchFileName(filePath->constData(), searchPattern.constData());
}
else
{
Expand All @@ -847,7 +845,7 @@ int FS1::findAllPaths(String searchPattern, int flags, FS1::PathList& found)
{
DENG2_FOR_EACH_CONST(LumpMappings, i, d->lumpMappings)
{
if(!F_MatchFileName(i->first.toUtf8().constData(), searchPatternUtf8.constData())) continue;
if(!F_MatchFileName(i->first.constData(), searchPattern.constData())) continue;

found.push_back(PathListItem(i->first, 0 /*only filepaths (i.e., leaves) can be mapped to lumps*/));
}
Expand Down Expand Up @@ -888,8 +886,7 @@ int FS1::findAllPaths(String searchPattern, int flags, FS1::PathList& found)
if(Str_Compare(&fd.name, ".") && Str_Compare(&fd.name, ".."))
{
String foundPath = searchDirectory / NativePath(Str_Text(&fd.name)).withSeparators('/');
QByteArray foundPathUtf8 = foundPath.toUtf8();
if(!F_MatchFileName(foundPathUtf8.constData(), searchPatternUtf8.constData())) continue;
if(!F_MatchFileName(foundPath.constData(), searchPattern.constData())) continue;

nativeFilePaths.push_back(PathListItem(foundPath, fd.attrib));
}
Expand Down
19 changes: 11 additions & 8 deletions doomsday/engine/src/filesys/fs_util.cpp
Expand Up @@ -622,22 +622,25 @@ const char* F_PrettyPath(const char* path)
#undef NUM_BUFS
}

int F_MatchFileName(const char* string, const char* pattern)
bool F_MatchFileName(QChar const *string, QChar const *pattern)
{
const char* in = string, *st = pattern;
static QChar const ASTERISK('*');
static QChar const QUESTION_MARK('?');

while(*in)
QChar const *in = string, *st = pattern;

while(!in->isNull())
{
if(*st == '*')
if(*st == ASTERISK)
{
st++;
continue;
}

if(*st != '?' && (tolower((unsigned char) *st) != tolower((unsigned char) *in)))
if(*st != QUESTION_MARK && st->toLower() != in->toLower())
{
// A mismatch. Hmm. Go back to a previous '*'.
while(st >= pattern && *st != '*')
while(st >= pattern && *st != ASTERISK)
st--;
if(st < pattern)
return false; // No match!
Expand All @@ -650,10 +653,10 @@ int F_MatchFileName(const char* string, const char* pattern)
}

// Match is good if the end of the pattern was reached.
while(*st == '*')
while(*st == ASTERISK)
st++; // Skip remaining asterisks.

return *st == 0;
return st->isNull();
}

boolean F_Dump(void const* data, size_t size, char const* path)
Expand Down

0 comments on commit b1a14dc

Please sign in to comment.