diff options
Diffstat (limited to 'backends/fs')
-rw-r--r-- | backends/fs/.cvsignore | 1 | ||||
-rw-r--r-- | backends/fs/fs.cpp | 78 | ||||
-rw-r--r-- | backends/fs/fs.h | 150 | ||||
-rw-r--r-- | backends/fs/morphos/abox-fs.cpp | 34 | ||||
-rw-r--r-- | backends/fs/palmos/palmos-fs.cpp | 21 | ||||
-rw-r--r-- | backends/fs/posix/posix-fs.cpp | 22 | ||||
-rw-r--r-- | backends/fs/windows/windows-fs.cpp | 23 |
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) { |