Add a 'flat' option to FSDirectory to allow searching recursively for files in subdirectories

svn-id: r41090
This commit is contained in:
Willem Jan Palenstijn 2009-06-01 00:01:32 +00:00
parent 9c8c1cb080
commit 6e38259270
4 changed files with 39 additions and 28 deletions

View file

@ -111,16 +111,16 @@ void SearchSet::add(const String &name, Archive *archive, int priority, bool aut
}
void SearchSet::addDirectory(const String &name, const String &directory, int priority, int depth) {
void SearchSet::addDirectory(const String &name, const String &directory, int priority, int depth, bool flat) {
FSNode dir(directory);
addDirectory(name, dir, priority, depth);
addDirectory(name, dir, priority, depth, flat);
}
void SearchSet::addDirectory(const String &name, const FSNode &dir, int priority, int depth) {
void SearchSet::addDirectory(const String &name, const FSNode &dir, int priority, int depth, bool flat) {
if (!dir.exists() || !dir.isDirectory())
return;
add(name, new FSDirectory(dir, depth), priority);
add(name, new FSDirectory(dir, depth, flat), priority);
}

View file

@ -161,12 +161,12 @@ public:
/**
* Create and add a FSDirectory by name
*/
void addDirectory(const String &name, const String &directory, int priority = 0, int depth = 1);
void addDirectory(const String &name, const String &directory, int priority = 0, int depth = 1, bool flat = false);
/**
* Create and add a FSDirectory by FSNode
*/
void addDirectory(const String &name, const FSNode &directory, int priority = 0, int depth = 1);
void addDirectory(const String &name, const FSNode &directory, int priority = 0, int depth = 1, bool flat = false);
/**
* Remove an archive from the searchable set.

View file

@ -163,22 +163,22 @@ Common::WriteStream *FSNode::createWriteStream() const {
return _realNode->createWriteStream();
}
FSDirectory::FSDirectory(const FSNode &node, int depth)
: _node(node), _cached(false), _depth(depth) {
FSDirectory::FSDirectory(const FSNode &node, int depth, bool flat)
: _node(node), _cached(false), _depth(depth), _flat(flat) {
}
FSDirectory::FSDirectory(const String &prefix, const FSNode &node, int depth)
: _node(node), _cached(false), _depth(depth) {
FSDirectory::FSDirectory(const String &prefix, const FSNode &node, int depth, bool flat)
: _node(node), _cached(false), _depth(depth), _flat(flat) {
setPrefix(prefix);
}
FSDirectory::FSDirectory(const String &name, int depth)
: _node(name), _cached(false), _depth(depth) {
FSDirectory::FSDirectory(const String &name, int depth, bool flat)
: _node(name), _cached(false), _depth(depth), _flat(flat) {
}
FSDirectory::FSDirectory(const String &prefix, const String &name, int depth)
: _node(name), _cached(false), _depth(depth) {
FSDirectory::FSDirectory(const String &prefix, const String &name, int depth, bool flat)
: _node(name), _cached(false), _depth(depth), _flat(flat) {
setPrefix(prefix);
}
@ -248,11 +248,11 @@ SeekableReadStream *FSDirectory::createReadStreamForMember(const String &name) c
return stream;
}
FSDirectory *FSDirectory::getSubDirectory(const String &name, int depth) {
return getSubDirectory(String::emptyString, name, depth);
FSDirectory *FSDirectory::getSubDirectory(const String &name, int depth, bool flat) {
return getSubDirectory(String::emptyString, name, depth, flat);
}
FSDirectory *FSDirectory::getSubDirectory(const String &prefix, const String &name, int depth) {
FSDirectory *FSDirectory::getSubDirectory(const String &prefix, const String &name, int depth, bool flat) {
if (name.empty() || !_node.isDirectory())
return 0;
@ -260,7 +260,7 @@ FSDirectory *FSDirectory::getSubDirectory(const String &prefix, const String &na
if (!node)
return 0;
return new FSDirectory(prefix, *node, depth);
return new FSDirectory(prefix, *node, depth, flat);
}
void FSDirectory::cacheDirectoryRecursive(FSNode node, int depth, const String& prefix) const {
@ -280,10 +280,13 @@ void FSDirectory::cacheDirectoryRecursive(FSNode node, int depth, const String&
// since the hashmap is case insensitive, we need to check for clashes when caching
if (it->isDirectory()) {
if (_subDirCache.contains(lowercaseName)) {
if (!_flat && _subDirCache.contains(lowercaseName)) {
warning("FSDirectory::cacheDirectory: name clash when building cache, ignoring sub-directory '%s'", name.c_str());
} else {
cacheDirectoryRecursive(*it, depth - 1, lowercaseName + "/");
if (_subDirCache.contains(lowercaseName)) {
warning("FSDirectory::cacheDirectory: name clash when building subDirCache with subdirectory '%s'", name.c_str());
}
cacheDirectoryRecursive(*it, depth - 1, _flat ? prefix : lowercaseName + "/");
_subDirCache[lowercaseName] = *it;
}
} else {

View file

@ -232,8 +232,8 @@ public:
*
* FSDirectory can represent a single directory, or a tree with specified depth,
* depending on the value passed to the 'depth' parameter in the constructors.
* Filenames are cached with their relative path, with elements separated by
* slashes, e.g.:
* In the default mode, filenames are cached with their relative path,
* with elements separated by slashes, e.g.:
*
* c:\my\data\file.ext
*
@ -247,11 +247,16 @@ public:
* hasFile(), listMatchingMembers() and listMembers(). Please see the function
* specific comments for more information.
*
* If the 'flat' argument to the constructor is true, files in subdirectories
* are cached without the relative path, so in the example above
* c:\my\data\file.ext would be cached as file.ext.
*
* Client code can customize cache by using the constructors with the 'prefix'
* parameter. In this case, the prefix is prepended to each entry in the cache,
* and effectively treated as a 'virtual' parent subdirectory. FSDirectory adds
* a trailing slash to prefix if needed. Following on with the previous example
* and using 'your' as prefix, the cache entry would have been 'your/data/file.ext'.
* This is done both in non-flat and flat mode.
*
*/
class FSDirectory : public Archive {
@ -266,6 +271,7 @@ class FSDirectory : public Archive {
mutable NodeCache _fileCache, _subDirCache;
mutable bool _cached;
mutable int _depth;
mutable bool _flat;
// look for a match
FSNode *lookupCache(NodeCache &cache, const String &name) const;
@ -282,15 +288,17 @@ public:
* unbound FSDirectory if name is not found on the filesystem or if the node is not a
* valid directory.
*/
FSDirectory(const String &name, int depth = 1);
FSDirectory(const FSNode &node, int depth = 1);
FSDirectory(const String &name, int depth = 1, bool flat = false);
FSDirectory(const FSNode &node, int depth = 1, bool flat = false);
/**
* Create a FSDirectory representing a tree with the specified depth. The parameter
* prefix is prepended to the keys in the cache. See class comment.
*/
FSDirectory(const String &prefix, const String &name, int depth = 1);
FSDirectory(const String &prefix, const FSNode &node, int depth = 1);
FSDirectory(const String &prefix, const String &name, int depth = 1,
bool flat = false);
FSDirectory(const String &prefix, const FSNode &node, int depth = 1,
bool flat = false);
virtual ~FSDirectory();
@ -304,8 +312,8 @@ public:
* for an explanation of the prefix parameter.
* @return a new FSDirectory instance
*/
FSDirectory *getSubDirectory(const String &name, int depth = 1);
FSDirectory *getSubDirectory(const String &prefix, const String &name, int depth = 1);
FSDirectory *getSubDirectory(const String &name, int depth = 1, bool flat = false);
FSDirectory *getSubDirectory(const String &prefix, const String &name, int depth = 1, bool flat = false);
/**
* Checks for existence in the cache. A full match of relative path and filename is needed