Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor|FS|libcore: Added FileIndex as a separate class
The index of files was previously an internal part of FileSystem, however now it is a class of its own to facilitate observable and custom indices.
- Loading branch information
Showing
7 changed files
with
315 additions
and
96 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
#include "filesys/fileindex.h" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
/** @file fileindex.h Index for looking up files of specific type. | ||
* | ||
* @authors Copyright (c) 2014 Jaakko Keränen <jaakko.keranen@iki.fi> | ||
* | ||
* @par License | ||
* LGPL: http://www.gnu.org/licenses/lgpl.html | ||
* | ||
* <small>This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU Lesser General Public License as published by | ||
* the Free Software Foundation; either version 3 of the License, or (at your | ||
* option) any later version. This program is distributed in the hope that it | ||
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty | ||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser | ||
* General Public License for more details. You should have received a copy of | ||
* the GNU Lesser General Public License along with this program; if not, see: | ||
* http://www.gnu.org/licenses</small> | ||
*/ | ||
|
||
#ifndef LIBDENG2_FILEINDEX_H | ||
#define LIBDENG2_FILEINDEX_H | ||
|
||
#include "../File" | ||
|
||
#include <map> | ||
#include <list> | ||
#include <utility> | ||
|
||
namespace de { | ||
|
||
class File; | ||
|
||
/** | ||
* Indexes files for quick access. | ||
* | ||
* @ingroup fs | ||
*/ | ||
class FileIndex | ||
{ | ||
public: | ||
typedef std::multimap<String, File *> Index; | ||
typedef std::pair<Index::iterator, Index::iterator> IndexRange; | ||
typedef std::pair<Index::const_iterator, Index::const_iterator> ConstIndexRange; | ||
typedef std::list<File *> FoundFiles; | ||
|
||
class IPredicate | ||
{ | ||
public: | ||
virtual ~IPredicate() {} | ||
|
||
/** | ||
* Determines if a file should be included in the index. | ||
* @param file File. | ||
* | ||
* @return @c true to index file, @c false to ignore. | ||
*/ | ||
virtual bool shouldIncludeInIndex(File const &file) const = 0; | ||
}; | ||
|
||
DENG2_DEFINE_AUDIENCE2(Addition, void fileAdded (File const &, FileIndex &)) | ||
DENG2_DEFINE_AUDIENCE2(Removal, void fileRemoved(File const &, FileIndex &)) | ||
|
||
public: | ||
FileIndex(); | ||
|
||
/** | ||
* Sets the predicate that determines whether a file should be included in the | ||
* index. | ||
* | ||
* @param predicate Predicate for inclusion. Must exist while the index is being | ||
* used. | ||
*/ | ||
void setPredicate(IPredicate const &predicate); | ||
|
||
/** | ||
* Adds a file to the index if the predicate permits. | ||
* | ||
* @param file File. | ||
* | ||
* @return @c true, if the file was added to the index. | ||
*/ | ||
bool maybeAdd(File const &file); | ||
|
||
/** | ||
* Removes a file from the index, if it has been indexed. If not, nothing is done. | ||
* | ||
* @param file File. | ||
*/ | ||
void remove(File const &file); | ||
|
||
int size() const; | ||
|
||
void findPartialPath(String const &path, FoundFiles &found) const; | ||
|
||
void print() const; | ||
|
||
// C++ iterator: | ||
typedef Index::const_iterator const_iterator; | ||
Index::const_iterator begin() const; | ||
Index::const_iterator end() const; | ||
|
||
private: | ||
DENG2_PRIVATE(d) | ||
}; | ||
|
||
} // namespace de | ||
|
||
#endif // LIBDENG2_FILEINDEX_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
/** @file fileindex.cpp Index for looking up files of specific type. | ||
* | ||
* @authors Copyright (c) 2014 Jaakko Keränen <jaakko.keranen@iki.fi> | ||
* | ||
* @par License | ||
* LGPL: http://www.gnu.org/licenses/lgpl.html | ||
* | ||
* <small>This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU Lesser General Public License as published by | ||
* the Free Software Foundation; either version 3 of the License, or (at your | ||
* option) any later version. This program is distributed in the hope that it | ||
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty | ||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser | ||
* General Public License for more details. You should have received a copy of | ||
* the GNU Lesser General Public License along with this program; if not, see: | ||
* http://www.gnu.org/licenses</small> | ||
*/ | ||
|
||
#include "de/FileIndex" | ||
#include "de/ReadWriteLockable" | ||
|
||
namespace de { | ||
|
||
DENG2_PIMPL(FileIndex), public ReadWriteLockable | ||
{ | ||
IPredicate const *predicate; | ||
Index index; | ||
|
||
Instance(Public *i) | ||
: Base(i) | ||
, predicate(0) | ||
{} | ||
|
||
static String indexedName(File const &file) | ||
{ | ||
return file.name().lower(); | ||
} | ||
|
||
void add(File const &file) | ||
{ | ||
DENG2_GUARD_WRITE(this); | ||
|
||
index.insert(std::pair<String, File *>(indexedName(file), const_cast<File *>(&file))); | ||
} | ||
|
||
void remove(File const &file) | ||
{ | ||
DENG2_GUARD_WRITE(this); | ||
|
||
if(index.empty()) | ||
{ | ||
return; | ||
} | ||
|
||
// Look up the ones that might be this file. | ||
IndexRange range = index.equal_range(indexedName(file)); | ||
|
||
for(Index::iterator i = range.first; i != range.second; ++i) | ||
{ | ||
if(i->second == &file) | ||
{ | ||
// This is the one to deindex. | ||
index.erase(i); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
void findPartialPath(String const &path, FoundFiles &found) const | ||
{ | ||
String baseName = path.fileName().lower(); | ||
String dir = path.fileNamePath().lower(); | ||
|
||
if(!dir.empty() && !dir.beginsWith("/")) | ||
{ | ||
// Always begin with a slash. We don't want to match partial folder names. | ||
dir = "/" + dir; | ||
} | ||
|
||
DENG2_GUARD_READ(this); | ||
|
||
ConstIndexRange range = index.equal_range(baseName); | ||
for(Index::const_iterator i = range.first; i != range.second; ++i) | ||
{ | ||
File *file = i->second; | ||
if(file->path().fileNamePath().endsWith(dir, Qt::CaseInsensitive)) | ||
{ | ||
found.push_back(file); | ||
} | ||
} | ||
} | ||
|
||
DENG2_PIMPL_AUDIENCE(Addition) | ||
DENG2_PIMPL_AUDIENCE(Removal) | ||
}; | ||
|
||
DENG2_AUDIENCE_METHOD(FileIndex, Addition) | ||
DENG2_AUDIENCE_METHOD(FileIndex, Removal) | ||
|
||
FileIndex::FileIndex() : d(new Instance(this)) | ||
{} | ||
|
||
void FileIndex::setPredicate(IPredicate const &predicate) | ||
{ | ||
d->predicate = &predicate; | ||
} | ||
|
||
bool FileIndex::maybeAdd(File const &file) | ||
{ | ||
if(d->predicate && !d->predicate->shouldIncludeInIndex(file)) | ||
{ | ||
return false; | ||
} | ||
|
||
d->add(file); | ||
|
||
// Notify audience. | ||
DENG2_FOR_AUDIENCE2(Addition, i) | ||
{ | ||
i->fileAdded(file, *this); | ||
} | ||
|
||
return true; | ||
} | ||
|
||
void FileIndex::remove(File const &file) | ||
{ | ||
d->remove(file); | ||
|
||
// Notify audience. | ||
DENG2_FOR_AUDIENCE2(Removal, i) | ||
{ | ||
i->fileRemoved(file, *this); | ||
} | ||
} | ||
|
||
int FileIndex::size() const | ||
{ | ||
return d->index.size(); | ||
} | ||
|
||
void FileIndex::findPartialPath(String const &path, FoundFiles &found) const | ||
{ | ||
d->findPartialPath(path, found); | ||
} | ||
|
||
FileIndex::Index::const_iterator FileIndex::begin() const | ||
{ | ||
return d.getConst()->index.begin(); | ||
} | ||
|
||
FileIndex::Index::const_iterator FileIndex::end() const | ||
{ | ||
return d.getConst()->index.end(); | ||
} | ||
|
||
void FileIndex::print() const | ||
{ | ||
for(Index::const_iterator i = d->index.begin(); i != d->index.end(); ++i) | ||
{ | ||
LOG_TRACE("\"%s\": ") << i->first << i->second->description(); | ||
} | ||
} | ||
|
||
} // namespace de |
Oops, something went wrong.