aboutsummaryrefslogtreecommitdiff
path: root/backends/fs
diff options
context:
space:
mode:
authorMax Horn2004-11-20 21:35:49 +0000
committerMax Horn2004-11-20 21:35:49 +0000
commit5d9b35510d7d6aad9408e12aaebed2a79e3ed826 (patch)
treea984b512f4bebfe2d001ab05eab21bd0c7f69b3b /backends/fs
parentc93f57b112cc1684a9d7d90587ff5de19a1530bd (diff)
downloadscummvm-rg350-5d9b35510d7d6aad9408e12aaebed2a79e3ed826.tar.gz
scummvm-rg350-5d9b35510d7d6aad9408e12aaebed2a79e3ed826.tar.bz2
scummvm-rg350-5d9b35510d7d6aad9408e12aaebed2a79e3ed826.zip
Changed the FilesystemNode implementation to make it easier to use (client code doesn't have to worry about the memory managment anymore, it's all 'automatic' now). May have introduced a mem leak or two, please check :-)
svn-id: r15848
Diffstat (limited to 'backends/fs')
-rw-r--r--backends/fs/.cvsignore1
-rw-r--r--backends/fs/fs.cpp78
-rw-r--r--backends/fs/fs.h150
-rw-r--r--backends/fs/morphos/abox-fs.cpp34
-rw-r--r--backends/fs/palmos/palmos-fs.cpp21
-rw-r--r--backends/fs/posix/posix-fs.cpp22
-rw-r--r--backends/fs/windows/windows-fs.cpp23
7 files changed, 203 insertions, 126 deletions
diff --git a/backends/fs/.cvsignore b/backends/fs/.cvsignore
new file mode 100644
index 0000000000..39a06683b7
--- /dev/null
+++ b/backends/fs/.cvsignore
@@ -0,0 +1 @@
+.deps
diff --git a/backends/fs/fs.cpp b/backends/fs/fs.cpp
new file mode 100644
index 0000000000..1c9b7efe5d
--- /dev/null
+++ b/backends/fs/fs.cpp
@@ -0,0 +1,78 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2002-2004 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#include "stdafx.h"
+
+#include "fs.h"
+
+FilesystemNode AbstractFilesystemNode::wrap(AbstractFilesystemNode *node) {
+ FilesystemNode wrapper;
+ wrapper._realNode = node;
+ return wrapper;
+}
+
+
+FilesystemNode::FilesystemNode() {
+ _realNode = getRoot();
+ _refCount = new int(1);
+}
+
+FilesystemNode::FilesystemNode(const FilesystemNode &node)
+ : AbstractFilesystemNode() {
+ _realNode = node._realNode;
+ _refCount = node._refCount;
+ ++(*_refCount);
+}
+
+#ifdef MACOSX
+FilesystemNode::FilesystemNode(const String &p) {
+ _realNode = getNodeForPath(p);
+ _refCount = new int(1);
+}
+#endif
+
+FilesystemNode::~FilesystemNode() {
+ decRefCount();
+}
+
+void FilesystemNode::decRefCount() {
+ --(*_refCount);
+ if (*_refCount <= 0) {
+ delete _refCount;
+ delete _realNode;
+ }
+}
+
+FilesystemNode &FilesystemNode::operator =(const FilesystemNode &node) {
+ ++(*node._refCount);
+
+ decRefCount();
+
+ _realNode = node._realNode;
+ _refCount = node._refCount;
+
+ return *this;
+}
+
+FilesystemNode FilesystemNode::getParent() const {
+ FilesystemNode wrapper;
+ wrapper._realNode = _realNode->parent();
+ return wrapper;
+}
diff --git a/backends/fs/fs.h b/backends/fs/fs.h
index 2f7e4fa4cd..bc72cccc79 100644
--- a/backends/fs/fs.h
+++ b/backends/fs/fs.h
@@ -58,15 +58,40 @@
#include "common/array.h"
#include "common/str.h"
-class FSList;
+class FilesystemNode;
+
+
+/**
+ * List of multiple file system nodes. E.g. the contents of a given directory.
+ */
+class FSList : public Common::Array<FilesystemNode> {
+};
+
/**
* File system node.
*/
-class FilesystemNode {
+class AbstractFilesystemNode {
protected:
+ friend class FilesystemNode;
typedef Common::String String;
+ /**
+ * The parent node of this directory.
+ * The parent of the root is the root itself.
+ */
+ virtual AbstractFilesystemNode *parent() const = 0;
+
+ /**
+ * This method is a rather ugly hack which is used internally by the
+ * actual node implementions to wrap up raw nodes inside FilesystemNode
+ * objects. We probably want to get rid of this eventually and replace it
+ * with a cleaner / more elegant solution, but for now it works.
+ * @note This takes over ownership of node. Do not delete it yourself,
+ * else you'll get ugly crashes. You've been warned!
+ */
+ static FilesystemNode wrap(AbstractFilesystemNode *node);
+
public:
/**
@@ -78,25 +103,7 @@ public:
kListAll = 3
} ListMode;
- /**
- * Returns a special node representing the FS root. The starting point for
- * any file system browsing.
- * On Unix, this will be simply the node for / (the root directory).
- * On Windows, it will be a special node which "contains" all drives (C:, D:, E:).
- */
- static FilesystemNode *getRoot();
-
-#ifdef MACOSX
- /*
- * Construct a node based on a path; the path is in the same format as it
- * would be for calls to fopen().
- *
- * I.e. getNodeForPath(oldNode.path()) should create a new node identical to oldNode.
- */
- static FilesystemNode *getNodeForPath(const String &path);
-#endif
-
- virtual ~FilesystemNode() {}
+ virtual ~AbstractFilesystemNode() {}
/**
* Return display name, used by e.g. the GUI to present the file in the file browser.
@@ -123,78 +130,69 @@ public:
* List the content of this directory node.
* If this node is not a directory, throw an exception or call error().
*/
- virtual FSList *listDir(ListMode mode = kListDirectoriesOnly) const = 0;
-
- /**
- * The parent node of this directory.
- * The parent of the root is the root itself
- */
- virtual FilesystemNode *parent() const = 0;
+ virtual FSList listDir(ListMode mode = kListDirectoriesOnly) const = 0;
/**
- * Return a clone of this node allocated with new().
- */
- virtual FilesystemNode *clone() const = 0;
-
- /**
* Compare the name of this node to the name of another.
*/
- virtual bool operator< (const FilesystemNode& node) const
+ virtual bool operator< (const AbstractFilesystemNode& node) const
{
return scumm_stricmp(displayName().c_str(), node.displayName().c_str()) < 0;
}
};
+class FilesystemNode : public AbstractFilesystemNode {
+ friend class AbstractFilesystemNode;
+
+ typedef Common::String String;
+private:
+ AbstractFilesystemNode *_realNode;
+ int *_refCount;
+
+ /**
+ * Returns a special node representing the FS root. The starting point for
+ * any file system browsing.
+ * On Unix, this will be simply the node for / (the root directory).
+ * On Windows, it will be a special node which "contains" all drives (C:, D:, E:).
+ */
+ static AbstractFilesystemNode *getRoot();
+
+#ifdef MACOSX
+ /*
+ * Construct a node based on a path; the path is in the same format as it
+ * would be for calls to fopen().
+ *
+ * I.e. getNodeForPath(oldNode.path()) should create a new node identical to oldNode.
+ */
+ static AbstractFilesystemNode *getNodeForPath(const String &path);
+#endif
+
-/**
- * Sorted list of multiple file system nodes. E.g. the contents of a given directory.
- */
-class FSList : private Common::Array<FilesystemNode *> {
public:
- class const_iterator {
- friend class FSList;
- FilesystemNode **_data;
- const_iterator(FilesystemNode **data) : _data(data) { }
- public:
- const FilesystemNode &operator *() const { return **_data; }
- const FilesystemNode *operator->() const { return *_data; }
- bool operator !=(const const_iterator &iter) const { return _data != iter._data; }
- void operator ++() { ++_data; }
- };
-
- ~FSList() {
- for (int i = 0; i < _size; i++)
- delete _data[i];
- }
+ FilesystemNode();
+ FilesystemNode(const FilesystemNode &node);
+#ifdef MACOSX
+ FilesystemNode(const String &path);
+#endif
+ ~FilesystemNode();
- void push_back(const FilesystemNode &element) {
- ensureCapacity(_size + 1);
- // Determine where to insert the item.
- // TODO this is inefficient, should use binary search instead
- int i = 0;
- while (i < _size && *_data[i] < element)
- i++;
- if (i < _size)
- memmove(&_data[i + 1], &_data[i], (_size - i) * sizeof(FilesystemNode *));
- _data[i] = element.clone();
- _size++;
- }
+ FilesystemNode &operator =(const FilesystemNode &node);
- const FilesystemNode& operator [](int idx) const {
- assert(idx >= 0 && idx < _size);
- return *_data[idx];
- }
+ FilesystemNode getParent() const;
- int size() const { return _size; }
- const_iterator begin() const {
- return const_iterator(_data);
- }
+ virtual String displayName() const { return _realNode->displayName(); }
+ virtual bool isValid() const { return _realNode->isValid(); }
+ virtual bool isDirectory() const { return _realNode->isDirectory(); }
+ virtual String path() const { return _realNode->path(); }
- const_iterator end() const {
- return const_iterator(_data + _size);
- }
+ virtual FSList listDir(ListMode mode = kListDirectoriesOnly) const { return _realNode->listDir(mode); }
+
+protected:
+ void decRefCount();
+ virtual AbstractFilesystemNode *parent() const { return 0; }
};
+
#endif
diff --git a/backends/fs/morphos/abox-fs.cpp b/backends/fs/morphos/abox-fs.cpp
index e535244875..712427b8cc 100644
--- a/backends/fs/morphos/abox-fs.cpp
+++ b/backends/fs/morphos/abox-fs.cpp
@@ -31,7 +31,7 @@
* Implementation of the ScummVM file system API based on the MorphOS A-Box API.
*/
-class ABoxFilesystemNode : public FilesystemNode {
+class ABoxFilesystemNode : public AbstractFilesystemNode {
protected:
BPTR _lock;
String _displayName;
@@ -50,14 +50,14 @@ class ABoxFilesystemNode : public FilesystemNode {
virtual bool isDirectory() const { return _isDirectory; }
virtual String path() const { return _path; }
- virtual FSList *listDir(ListMode mode = kListDirectoriesOnly) const;
- static FSList *listRoot();
- virtual FilesystemNode *parent() const;
- virtual FilesystemNode *clone() const { return new ABoxFilesystemNode(this); }
+ virtual FSList listDir(ListMode mode = kListDirectoriesOnly) const;
+ static FSList listRoot();
+ virtual AbstractFilesystemNode *parent() const;
+ virtual AbstractFilesystemNode *clone() const { return new ABoxFilesystemNode(this); }
};
-FilesystemNode *FilesystemNode::getRoot()
+AbstractFilesystemNode *FilesystemNode::getRoot()
{
return new ABoxFilesystemNode();
}
@@ -137,9 +137,9 @@ ABoxFilesystemNode::~ABoxFilesystemNode()
}
}
-FSList *ABoxFilesystemNode::listDir(ListMode mode) const
+FSList ABoxFilesystemNode::listDir(ListMode mode) const
{
- FSList *myList = new FSList();
+ FSList myList;
if (!_isValid)
error("listDir() called on invalid node");
@@ -182,8 +182,9 @@ FSList *ABoxFilesystemNode::listDir(ListMode mode) const
if (entry)
{
if (entry->isValid())
- myList->push_back(*entry);
- delete entry;
+ myList.push_back(wrap(entry));
+ else
+ delete entry;
}
UnLock(lock);
}
@@ -199,9 +200,9 @@ FSList *ABoxFilesystemNode::listDir(ListMode mode) const
return myList;
}
-FilesystemNode *ABoxFilesystemNode::parent() const
+AbstractFilesystemNode *ABoxFilesystemNode::parent() const
{
- FilesystemNode *node = NULL;
+ AbstractFilesystemNode *node = NULL;
if (!_isDirectory)
error("parent() called on file node");
@@ -224,9 +225,9 @@ FilesystemNode *ABoxFilesystemNode::parent() const
return node;
}
-FSList *ABoxFilesystemNode::listRoot()
+FSList ABoxFilesystemNode::listRoot()
{
- FSList *myList = new FSList();
+ FSList myList;
DosList *dosList;
CONST ULONG lockDosListFlags = LDF_READ | LDF_VOLUMES;
char name[256];
@@ -261,8 +262,9 @@ FSList *ABoxFilesystemNode::listRoot()
if (entry)
{
if (entry->isValid())
- myList->push_back(*entry);
- delete entry;
+ myList.push_back(wrap(entry));
+ else
+ delete entry;
}
UnLock(volume_lock);
}
diff --git a/backends/fs/palmos/palmos-fs.cpp b/backends/fs/palmos/palmos-fs.cpp
index 2a5c599e6c..aeecb38d43 100644
--- a/backends/fs/palmos/palmos-fs.cpp
+++ b/backends/fs/palmos/palmos-fs.cpp
@@ -29,7 +29,7 @@
* Implementation of the ScummVM file system API based on PalmOS VFS API.
*/
-class PalmOSFilesystemNode : public FilesystemNode {
+class PalmOSFilesystemNode : public AbstractFilesystemNode {
protected:
String _displayName;
bool _isDirectory;
@@ -47,15 +47,14 @@ public:
virtual bool isDirectory() const { return _isDirectory; }
virtual String path() const { return _path; }
- virtual FSList *listDir(ListMode) const;
- virtual FilesystemNode *parent() const;
- virtual FilesystemNode *clone() const { return new PalmOSFilesystemNode(this); }
+ virtual FSList listDir(ListMode) const;
+ virtual AbstractFilesystemNode *parent() const;
private:
- static void addFile (FSList* list, ListMode mode, const Char *base, FileInfoType* find_data);
+ static void addFile (FSList &list, ListMode mode, const Char *base, FileInfoType* find_data);
};
-void PalmOSFilesystemNode::addFile(FSList* list, ListMode mode, const char *base, FileInfoType* find_data) {
+void PalmOSFilesystemNode::addFile(FSList &list, ListMode mode, const char *base, FileInfoType* find_data) {
PalmOSFilesystemNode entry;
bool isDirectory;
@@ -74,10 +73,10 @@ void PalmOSFilesystemNode::addFile(FSList* list, ListMode mode, const char *base
entry._isValid = true;
entry._isPseudoRoot = false;
- list->push_back(entry);
+ list.push_back(wrap(new PalmOSFilesystemNode(&entry)));
}
-FilesystemNode *FilesystemNode::getRoot() {
+AbstractFilesystemNode *FilesystemNode::getRoot() {
return new PalmOSFilesystemNode();
}
@@ -97,9 +96,9 @@ PalmOSFilesystemNode::PalmOSFilesystemNode(const PalmOSFilesystemNode *node) {
_path = node->_path;
}
-FSList *PalmOSFilesystemNode::listDir(ListMode mode) const {
+FSList PalmOSFilesystemNode::listDir(ListMode mode) const {
- FSList *myList = new FSList();
+ FSList myList;
Err e;
Char nameP[256];
FileInfoType desc;
@@ -136,7 +135,7 @@ const char *lastPathComponent(const Common::String &str) {
return cur+1;
}
-FilesystemNode *PalmOSFilesystemNode::parent() const {
+AbstractFilesystemNode *PalmOSFilesystemNode::parent() const {
PalmOSFilesystemNode *p = new PalmOSFilesystemNode();
diff --git a/backends/fs/posix/posix-fs.cpp b/backends/fs/posix/posix-fs.cpp
index 86c29910b5..a2f35ad108 100644
--- a/backends/fs/posix/posix-fs.cpp
+++ b/backends/fs/posix/posix-fs.cpp
@@ -45,7 +45,7 @@
* Implementation of the ScummVM file system API based on POSIX.
*/
-class POSIXFilesystemNode : public FilesystemNode {
+class POSIXFilesystemNode : public AbstractFilesystemNode {
protected:
String _displayName;
bool _isDirectory;
@@ -62,9 +62,8 @@ public:
virtual bool isDirectory() const { return _isDirectory; }
virtual String path() const { return _path; }
- virtual FSList *listDir(ListMode mode = kListDirectoriesOnly) const;
- virtual FilesystemNode *parent() const;
- virtual FilesystemNode *clone() const { return new POSIXFilesystemNode(this); }
+ virtual FSList listDir(ListMode mode = kListDirectoriesOnly) const;
+ virtual AbstractFilesystemNode *parent() const;
};
@@ -79,12 +78,12 @@ static const char *lastPathComponent(const Common::String &str) {
return cur+1;
}
-FilesystemNode *FilesystemNode::getRoot() {
+AbstractFilesystemNode *FilesystemNode::getRoot() {
return new POSIXFilesystemNode();
}
#ifdef MACOSX
-FilesystemNode *FilesystemNode::getNodeForPath(const String &path) {
+AbstractFilesystemNode *FilesystemNode::getNodeForPath(const String &path) {
return new POSIXFilesystemNode(path);
}
#endif
@@ -140,15 +139,16 @@ POSIXFilesystemNode::POSIXFilesystemNode(const POSIXFilesystemNode *node) {
_path = node->_path;
}
-FSList *POSIXFilesystemNode::listDir(ListMode mode) const {
+FSList POSIXFilesystemNode::listDir(ListMode mode) const {
assert(_isDirectory);
DIR *dirp = opendir(_path.c_str());
struct stat st;
struct dirent *dp;
- FSList *myList = new FSList();
+ FSList myList;
- if (dirp == NULL) return myList;
+ if (dirp == NULL)
+ return myList;
// ... loop over dir entries using readdir
while ((dp = readdir(dirp)) != NULL) {
@@ -178,13 +178,13 @@ FSList *POSIXFilesystemNode::listDir(ListMode mode) const {
if (entry._isDirectory)
entry._path += "/";
- myList->push_back(entry);
+ myList.push_back(wrap(new POSIXFilesystemNode(&entry)));
}
closedir(dirp);
return myList;
}
-FilesystemNode *POSIXFilesystemNode::parent() const {
+AbstractFilesystemNode *POSIXFilesystemNode::parent() const {
POSIXFilesystemNode *p = new POSIXFilesystemNode();
// Root node is its own parent. Still we can't just return this
diff --git a/backends/fs/windows/windows-fs.cpp b/backends/fs/windows/windows-fs.cpp
index 0f6768c099..96231b9a53 100644
--- a/backends/fs/windows/windows-fs.cpp
+++ b/backends/fs/windows/windows-fs.cpp
@@ -31,7 +31,7 @@
* Implementation of the ScummVM file system API based on Windows API.
*/
-class WindowsFilesystemNode : public FilesystemNode {
+class WindowsFilesystemNode : public AbstractFilesystemNode {
protected:
String _displayName;
bool _isDirectory;
@@ -49,14 +49,13 @@ public:
virtual bool isDirectory() const { return _isDirectory; }
virtual String path() const { return _path; }
- virtual FSList *listDir(ListMode) const;
- virtual FilesystemNode *parent() const;
- virtual FilesystemNode *clone() const { return new WindowsFilesystemNode(this); }
+ virtual FSList listDir(ListMode) const;
+ virtual AbstractFilesystemNode *parent() const;
private:
static char *toAscii(TCHAR *x);
static TCHAR* toUnicode(char *x);
- static void addFile (FSList* list, ListMode mode, const char *base, WIN32_FIND_DATA* find_data);
+ static void addFile (FSList &list, ListMode mode, const char *base, WIN32_FIND_DATA* find_data);
};
@@ -82,7 +81,7 @@ TCHAR* WindowsFilesystemNode::toUnicode(char *x) {
#endif
}
-void WindowsFilesystemNode::addFile(FSList* list, ListMode mode, const char *base, WIN32_FIND_DATA* find_data) {
+void WindowsFilesystemNode::addFile(FSList &list, ListMode mode, const char *base, WIN32_FIND_DATA* find_data) {
WindowsFilesystemNode entry;
char *asciiName = toAscii(find_data->cFileName);
bool isDirectory;
@@ -106,10 +105,10 @@ void WindowsFilesystemNode::addFile(FSList* list, ListMode mode, const char *bas
entry._isValid = true;
entry._isPseudoRoot = false;
- list->push_back(entry);
+ list.push_back(wrap(new WindowsFilesystemNode(&entry)));
}
-FilesystemNode *FilesystemNode::getRoot() {
+AbstractFilesystemNode *FilesystemNode::getRoot() {
return new WindowsFilesystemNode();
}
@@ -137,10 +136,10 @@ WindowsFilesystemNode::WindowsFilesystemNode(const WindowsFilesystemNode *node)
_path = node->_path;
}
-FSList *WindowsFilesystemNode::listDir(ListMode mode) const {
+FSList WindowsFilesystemNode::listDir(ListMode mode) const {
assert(_isDirectory);
- FSList *myList = new FSList();
+ FSList myList;
if (_isPseudoRoot) {
#ifndef _WIN32_WCE
@@ -160,7 +159,7 @@ FSList *WindowsFilesystemNode::listDir(ListMode mode) const {
entry._isValid = true;
entry._isPseudoRoot = false;
entry._path = toAscii(current_drive);
- myList->push_back(entry);
+ myList.push_back(wrap(new WindowsFilesystemNode(&entry)));
}
#endif
}
@@ -196,7 +195,7 @@ const char *lastPathComponent(const Common::String &str) {
return cur + 1;
}
-FilesystemNode *WindowsFilesystemNode::parent() const {
+AbstractFilesystemNode *WindowsFilesystemNode::parent() const {
assert(_isValid || _isPseudoRoot);
WindowsFilesystemNode *p = new WindowsFilesystemNode();
if (!_isPseudoRoot && _path.size() > 3) {