aboutsummaryrefslogtreecommitdiff
path: root/common/fs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'common/fs.cpp')
-rw-r--r--common/fs.cpp210
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;
}