diff options
Diffstat (limited to 'common/fs.cpp')
-rw-r--r-- | common/fs.cpp | 210 |
1 files changed, 161 insertions, 49 deletions
diff --git a/common/fs.cpp b/common/fs.cpp index c33fc42223..3e0959b232 100644 --- a/common/fs.cpp +++ b/common/fs.cpp @@ -23,14 +23,45 @@ */ #include "common/stdafx.h" - -#include "backends/fs/abstract-fs.h" #include "common/util.h" +#include "backends/fs/abstract-fs.h" +#include "backends/fs/fs-factory-maker.cpp" +/* + * Simple DOS-style pattern matching function (understands * and ? like used in DOS). + * Taken from exult/files/listfiles.cc + */ +static bool matchString(const char *str, const char *pat) { + const char *p = 0; + const char *q = 0; + + for (;;) { + switch (*pat) { + case '*': + p = ++pat; + q = str; + break; -FilesystemNode::FilesystemNode(AbstractFilesystemNode *realNode) { - _realNode = realNode; - _refCount = new int(1); + default: + if (*pat != *str) { + if (p) { + pat = p; + str = ++q; + if(!*str) + return !*pat; + break; + } + else + return false; + } + // fallthrough + case '?': + if(!*str) + return !*pat; + pat++; + str++; + } + } } FilesystemNode::FilesystemNode() { @@ -38,6 +69,11 @@ FilesystemNode::FilesystemNode() { _refCount = 0; } +FilesystemNode::FilesystemNode(AbstractFilesystemNode *realNode) { + _realNode = realNode; + _refCount = new int(1); +} + FilesystemNode::FilesystemNode(const FilesystemNode &node) { _realNode = node._realNode; _refCount = node._refCount; @@ -46,10 +82,12 @@ FilesystemNode::FilesystemNode(const FilesystemNode &node) { } FilesystemNode::FilesystemNode(const Common::String &p) { + AbstractFilesystemFactory *factory = makeFSFactory(); + if (p.empty() || p == ".") - _realNode = AbstractFilesystemNode::getCurrentDirectory(); + _realNode = factory->makeCurrentDirectoryFileNode(); else - _realNode = AbstractFilesystemNode::getNodeForPath(p); + _realNode = factory->makeFileNodePath(p); _refCount = new int(1); } @@ -57,18 +95,7 @@ FilesystemNode::~FilesystemNode() { decRefCount(); } -void FilesystemNode::decRefCount() { - if (_refCount) { - assert(*_refCount > 0); - --(*_refCount); - if (*_refCount == 0) { - delete _refCount; - delete _realNode; - } - } -} - -FilesystemNode &FilesystemNode::operator =(const FilesystemNode &node) { +FilesystemNode &FilesystemNode::operator= (const FilesystemNode &node) { if (node._refCount) ++(*node._refCount); @@ -80,40 +107,50 @@ FilesystemNode &FilesystemNode::operator =(const FilesystemNode &node) { return *this; } -bool FilesystemNode::isValid() const { - if (_realNode == 0) +bool FilesystemNode::operator<(const FilesystemNode& node) const +{ + if (isDirectory() && !node.isDirectory()) + return true; + if (!isDirectory() && node.isDirectory()) return false; - return _realNode->isValid(); + + return scumm_stricmp(getDisplayName().c_str(), node.getDisplayName().c_str()) < 0; } -FilesystemNode FilesystemNode::getParent() const { - if (_realNode == 0) - return *this; - - AbstractFilesystemNode *node = _realNode->parent(); - if (node == 0) { - return *this; - } else { - return FilesystemNode(node); +void FilesystemNode::decRefCount() { + if (_refCount) { + assert(*_refCount > 0); + --(*_refCount); + if (*_refCount == 0) { + delete _refCount; + delete _realNode; + } } } +bool FilesystemNode::exists() const { + if (_realNode == 0) + return false; + + return _realNode->exists(); +} + FilesystemNode FilesystemNode::getChild(const Common::String &n) const { if (_realNode == 0) return *this; assert(_realNode->isDirectory()); - AbstractFilesystemNode *node = _realNode->child(n); + AbstractFilesystemNode *node = _realNode->getChild(n); return FilesystemNode(node); } -bool FilesystemNode::listDir(FSList &fslist, ListMode mode) const { +bool FilesystemNode::getChildren(FSList &fslist, ListMode mode, bool hidden) const { if (!_realNode || !_realNode->isDirectory()) return false; AbstractFSList tmp; - if (!_realNode->listDir(tmp, mode)) + if (!_realNode->getChildren(tmp, mode, hidden)) return false; fslist.clear(); @@ -124,33 +161,108 @@ bool FilesystemNode::listDir(FSList &fslist, ListMode mode) const { return true; } +Common::String FilesystemNode::getDisplayName() const { + assert(_realNode); + return _realNode->getDisplayName(); +} + +Common::String FilesystemNode::getName() const { + assert(_realNode); + return _realNode->getName(); +} + +FilesystemNode FilesystemNode::getParent() const { + if (_realNode == 0) + return *this; + + AbstractFilesystemNode *node = _realNode->getParent(); + if (node == 0) { + return *this; + } else { + return FilesystemNode(node); + } +} + +Common::String FilesystemNode::getPath() const { + assert(_realNode); + return _realNode->getPath(); +} + bool FilesystemNode::isDirectory() const { if (_realNode == 0) return false; + return _realNode->isDirectory(); } -Common::String FilesystemNode::displayName() const { - assert(_realNode); - return _realNode->displayName(); +bool FilesystemNode::isReadable() const { + if (_realNode == 0) + return false; + + return _realNode->isReadable(); } -Common::String FilesystemNode::name() const { - assert(_realNode); - return _realNode->name(); +bool FilesystemNode::isWritable() const { + if (_realNode == 0) + return false; + + return _realNode->isWritable(); } -Common::String FilesystemNode::path() const { - assert(_realNode); - return _realNode->path(); -} +bool FilesystemNode::lookupFile(FSList &results, FSList &fslist, Common::String &filename, bool hidden, bool exhaustive) const +{ + int matches = 0; + + for (FSList::iterator entry = fslist.begin(); entry != fslist.end(); ++entry) { + if (entry->isDirectory()) { + matches += lookupFileRec(results, *entry, filename, hidden, exhaustive); + } + } + return ((matches > 0) ? true : false); +} -bool FilesystemNode::operator< (const FilesystemNode& node) const +bool FilesystemNode::lookupFile(FSList &results, FilesystemNode &dir, Common::String &filename, bool hidden, bool exhaustive) const { - if (isDirectory() && !node.isDirectory()) - return true; - if (!isDirectory() && node.isDirectory()) + int matches; + + if (!dir.isDirectory()) return false; - return scumm_stricmp(displayName().c_str(), node.displayName().c_str()) < 0; + + matches = lookupFileRec(results, dir, filename, hidden, exhaustive); + + return ((matches > 0) ? true : false); +} + +int FilesystemNode::lookupFileRec(FSList &results, FilesystemNode &dir, Common::String &filename, bool hidden, bool exhaustive) const +{ + FSList entries; + FSList children; + int matches = 0; + dir.getChildren(entries, FilesystemNode::kListAll, hidden); + + //Breadth search (entries in the same level) + for (FSList::iterator entry = entries.begin(); entry != entries.end(); ++entry) { + if (entry->isDirectory()) { + children.push_back(*entry); + } else { + //TODO: here we assume all backends implement the lastPathComponent method. It is currently static, + // so it might be a good idea to include it inside the backend class. This would enforce its + // implementation by all ports. + if (matchString(lastPathComponent(entry->getPath()), filename.c_str())) { + results.push_back(*entry); + matches++; + + if (!exhaustive) + break; + } + } + } + + //Depth search (entries in lower levels) + for (FSList::iterator child = children.begin(); child != children.end(); ++child) { + matches += lookupFileRec(results, *child, filename, hidden, exhaustive); + } + + return matches; } |