From ab3c8e47b17f040602661afa5358751aad2c81b6 Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Mon, 24 Feb 2003 07:07:56 +0000 Subject: [PATCH] Handle up to two wildcards in GetDirListing --- stepmania/src/RageUtil.cpp | 70 ++++++++++++++++++++++---------------- stepmania/src/RageUtil.h | 4 ++- 2 files changed, 44 insertions(+), 30 deletions(-) diff --git a/stepmania/src/RageUtil.cpp b/stepmania/src/RageUtil.cpp index fbccb72b77..1cd62750a3 100644 --- a/stepmania/src/RageUtil.cpp +++ b/stepmania/src/RageUtil.cpp @@ -963,22 +963,6 @@ struct File { bool operator== (const File &rhs) const { return name==rhs.name; } bool operator< (const File &rhs) const { return name name.size()) return false; - return !strnicmp(name.c_str(), txt.c_str(), txt.size()); - } - - bool FilenameEndsWith(const CString &ext) const - { - if(ext.empty()) return true; - int ignore = int(name.size())-int(ext.size()); - if(ignore < 0) return false; - - return !stricmp(name.c_str()+ignore, ext.c_str()); - } - bool equal(const File &rhs) const { return name == rhs.name; } bool equal(const CString &rhs) const { return !stricmp(name.c_str(), rhs.c_str()); @@ -993,7 +977,9 @@ struct FileSet set files; RageTimer age; void LoadFromDir(const CString &dir); - void GetFilesStartingAndEndingWith(const CString &beginning, const CString &ending, vector &out, bool bOnlyDirs) const; + void GetFilesMatching( + const CString &beginning, const CString &containing, const CString &ending, + vector &out, bool bOnlyDirs) const; void GetFilesEqualTo(const CString &pat, vector &out, bool bOnlyDirs) const; }; @@ -1048,15 +1034,33 @@ void FileSet::LoadFromDir(const CString &dir) chdir(oldpath); } -void FileSet::GetFilesStartingAndEndingWith(const CString &beginning, const CString &ending, vector &out, bool bOnlyDirs) const +/* Search for "beginning*containing*ending". */ +void FileSet::GetFilesMatching(const CString &beginning, const CString &containing, const CString &ending, vector &out, bool bOnlyDirs) const { set::const_iterator i = files.lower_bound(File(beginning.c_str())); -// set::const_iterator end = files.upper_bound(File(beginning.c_str())); for( ; i != files.end(); ++i) { if(bOnlyDirs && !i->dir) continue; - if(!i->FilenameBeginsWith(beginning)) return; - if(!i->FilenameEndsWith(ending)) continue; + + /* Check beginning. */ + if(beginning.size() > i->name.size()) continue; /* can't start with it */ + if(strnicmp(i->name.c_str(), beginning.c_str(), beginning.size())) continue; /* doesn't start with it */ + + /* Position the end starts on: */ + int end_pos = int(i->name.size())-int(ending.size()); + + /* Check end. */ + if(end_pos < 0) continue; /* can't end with it */ + if(stricmp(i->name.c_str()+end_pos, ending.c_str())) continue; /* doesn't end with it */ + + /* Check containing. Do this last, since it's the slowest (substring + * search instead of string match). */ + if(containing.size()) + { + unsigned pos = i->name.find(containing, beginning.size()); + if(pos == i->name.npos) continue; /* doesn't contain it */ + if(pos + containing.size() > unsigned(end_pos)) continue; /* found it but it overlaps with the end */ + } out.push_back(i->name.c_str()); } @@ -1113,10 +1117,10 @@ bool FilenameDB::ResolvePath(CString &path) return true; } -void FilenameDB::GetFilesStartingAndEndingWith(const CString &dir, const CString &beginning, const CString &ending, vector &out, bool bOnlyDirs) +void FilenameDB::GetFilesMatching(const CString &dir, const CString &beginning, const CString &containing, const CString &ending, vector &out, bool bOnlyDirs) { FileSet &fs = GetFileSet(dir); - fs.GetFilesStartingAndEndingWith(beginning, ending, out, bOnlyDirs); + fs.GetFilesMatching(beginning, containing, ending, out, bOnlyDirs); } void FilenameDB::GetFilesEqualTo(const CString &dir, const CString &fn, vector &out, bool bOnlyDirs) @@ -1129,16 +1133,24 @@ void FilenameDB::GetFilesEqualTo(const CString &dir, const CString &fn, vector &out, bool bOnlyDirs) { /* Does this contain a wildcard? */ - unsigned pos = fn.find_first_of('*'); - if(pos == fn.npos) + unsigned first_pos = fn.find_first_of('*'); + if(first_pos == fn.npos) { /* No; just do a regular search. */ GetFilesEqualTo(dir, fn, out, bOnlyDirs); } else { - /* Only one *! */ - if(pos) - ASSERT(fn.find_first_of('*', pos+1) == fn.npos); - GetFilesStartingAndEndingWith(dir, fn.substr(0, pos), fn.substr(pos+1), out, bOnlyDirs); + unsigned second_pos = fn.find_first_of('*', first_pos+1); + if(second_pos == fn.npos) + { + /* Only one *: "A*B". */ + GetFilesMatching(dir, fn.substr(0, first_pos), "", fn.substr(first_pos+1), out, bOnlyDirs); + } else { + /* Two *s: "A*B*C". */ + GetFilesMatching(dir, + fn.substr(0, first_pos), + fn.substr(first_pos+1, second_pos-first_pos-1), + fn.substr(second_pos+1), out, bOnlyDirs); + } } } diff --git a/stepmania/src/RageUtil.h b/stepmania/src/RageUtil.h index 26b53b8e8f..e6522f0721 100644 --- a/stepmania/src/RageUtil.h +++ b/stepmania/src/RageUtil.h @@ -224,7 +224,9 @@ class FilenameDB map dirs; void GetFilesEqualTo(const CString &dir, const CString &fn, vector &out, bool bOnlyDirs); - void GetFilesStartingAndEndingWith(const CString &dir, const CString &beginning, const CString &ending, vector &out, bool bOnlyDirs); + void GetFilesMatching(const CString &dir, + const CString &beginning, const CString &containing, const CString &ending, + vector &out, bool bOnlyDirs); public: /* This handles at most one * wildcard. If we need anything more complicated,