diff options
author | Stephen Kennedy | 2008-09-26 21:53:08 +0000 |
---|---|---|
committer | Stephen Kennedy | 2008-09-26 21:53:08 +0000 |
commit | a7bb113e83c88fad3a23d408caa99f918fdb610a (patch) | |
tree | 698dd9d85abaa6a20957bfb9c0e006e9dd1dc8b3 /backends/fs | |
parent | 11c0a3bdedcdf5eb2618b9db67b559663fb93320 (diff) | |
parent | c1385076cbc57f1a4a52946a46b3ea06ecf37f37 (diff) | |
download | scummvm-rg350-a7bb113e83c88fad3a23d408caa99f918fdb610a.tar.gz scummvm-rg350-a7bb113e83c88fad3a23d408caa99f918fdb610a.tar.bz2 scummvm-rg350-a7bb113e83c88fad3a23d408caa99f918fdb610a.zip |
Merged revisions 33452-33453,33455-33459,33463-33464,33466-33471,33473-33474,33478,33490,33492,33495-33496,33509-33512,33518-33519,33522-33527,33529-33530,33537,33541,33544,33546,33550,33552-33554,33556,33558,33561-33562,33565,33568,33570,33574,33576,33578-33581,33584-33587,33590,33596,33604-33611,33614-33615,33617-33618,33620-33621,33623,33626-33627,33632-33633,33635,33637,33639-33640,33642-33645,33648,33654-33655,33664,33667-33670,33673-33674,33678,33682,33686-33691,33693,33696,33698,33700,33703,33708,33710,33712-33714,33716,33719,33721-33723,33725-33727,33729-33730,33733,33736,33742,33754,33756,33758,33761,33763,33766,33777,33781-33788,33790,33792-33793,33795,33797,33805,33807-33812,33815-33817,33819,33822,33826,33829,33837,33839,33844,33847,33858-33861,33864,33871-33873,33875,33877-33879,33886,33889-33892,33894,33896,33900,33902-33903,33919,33928,33930,33932-33936,33938-33940,33942-33943,33948,33950,33953,33967,33973,33976,33978,33980,33985,33991,33993,33999-34000,34006,34009,34011,34013,34015,34019,34021-34023,34025,34027-34028,34030,34032-34034,34036,34038-34039,34041,34046-34048,34050-34055,34057,34059-34065,34067,34072,34074,34076,34078-34081,34084,34086-34087,34089-34090,34093,34096-34102,34104,34107,34113,34116,34119,34122,34124,34126,34128,34131-34132,34135,34138,34141,34144,34146,34149,34152-34154,34156-34157,34160,34163-34164,34169,34173,34179-34194,34196-34198,34200-34201,34205-34206,34208-34217,34219-34225,34227-34228,34234-34237,34239-34249,34251-34279,34281-34284,34286-34288,34290-34320,34323-34324,34326,34328-34329,34332,34334,34336,34338-34340,34343-34353,34356-34357,34359-34371,34373,34375,34378,34381-34382,34384-34385,34389-34391,34393-34394,34396-34397,34399-34405,34407-34409,34411,34413,34415,34417-34420,34423-34426,34428-34438,34440-34454,34456-34458,34460,34462-34469,34472,34474,34479-34481,34483-34498,34501-34505,34508,34511-34518,34520-34524,34526-34563,34566-34569,34571-34590,34592,34595-34599,34602-34603,34605,34613-34615,34617,34619-34624,34627-34628,34630-34639,34642-34649 via svnmerge from
https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk
svn-id: r34654
Diffstat (limited to 'backends/fs')
35 files changed, 1198 insertions, 751 deletions
diff --git a/backends/fs/abstract-fs.cpp b/backends/fs/abstract-fs.cpp new file mode 100644 index 0000000000..6daad7152a --- /dev/null +++ b/backends/fs/abstract-fs.cpp @@ -0,0 +1,40 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + */ + +#include "backends/fs/abstract-fs.h" + +const char *AbstractFilesystemNode::lastPathComponent(const Common::String &str, const char sep) { + // TODO: Get rid of this eventually! Use Common::lastPathComponent instead + if(str.empty()) + return ""; + + const char *start = str.c_str(); + const char *cur = start + str.size() - 2; + + while (cur >= start && *cur != sep) { + --cur; + } + + return cur + 1; +} diff --git a/backends/fs/abstract-fs.h b/backends/fs/abstract-fs.h index 8125ad7d95..b3a652f2ae 100644 --- a/backends/fs/abstract-fs.h +++ b/backends/fs/abstract-fs.h @@ -43,28 +43,27 @@ typedef Common::Array<AbstractFilesystemNode *> AbstractFSList; */ class AbstractFilesystemNode { protected: - friend class FilesystemNode; - typedef Common::String String; - typedef FilesystemNode::ListMode ListMode; + friend class Common::FilesystemNode; + typedef Common::FilesystemNode::ListMode ListMode; /** - * Returns the child node with the given name. If no child with this name - * exists, returns 0. When called on a non-directory node, it should - * handle this gracefully by returning 0. + * Returns the child node with the given name. When called on a non-directory + * node, it should handle this gracefully by returning 0. + * When called with a name not matching any of the files/dirs contained in this + * directory, a valid node shold be returned, which returns 'false' upon calling + * the exists() method. The idea is that this node can then still can be used to + * create a new file via the openForWriting() method. * * Example: * Calling getChild() for a node with path "/foo/bar" using name="file.txt", * would produce a new node with "/foo/bar/file.txt" as path. * - * @note This function will append a separator char (\ or /) to the end of the - * path if needed. - * * @note Handling calls on non-dir nodes gracefully makes it possible to * switch to a lazy type detection scheme in the future. * * @param name String containing the name of the child to create a new node. */ - virtual AbstractFilesystemNode *getChild(const String &name) const = 0; + virtual AbstractFilesystemNode *getChild(const Common::String &name) const = 0; /** * The parent node of this directory. @@ -72,6 +71,19 @@ protected: */ virtual AbstractFilesystemNode *getParent() const = 0; + /** + * Returns the last component of a given path. + * + * Examples: + * /foo/bar.txt would return /bar.txt + * /foo/bar/ would return /bar/ + * + * @param str String containing the path. + * @param sep character used to separate path components + * @return Pointer to the first char of the last component inside str. + */ + static const char *lastPathComponent(const Common::String &str, const char sep); + public: /** * Destructor. @@ -100,7 +112,7 @@ public: * * @note By default, this method returns the value of getName(). */ - virtual String getDisplayName() const { return getName(); } + virtual Common::String getDisplayName() const { return getName(); } /** * Returns the last component of the path pointed by this FilesystemNode. @@ -111,12 +123,12 @@ public: * * @note This method is very architecture dependent, please check the concrete implementation for more information. */ - virtual String getName() const = 0; + virtual Common::String getName() const = 0; /** * Returns the 'path' of the current node, usable in fopen(). */ - virtual String getPath() const = 0; + virtual Common::String getPath() const = 0; /** * Indicates whether this path refers to a directory or not. @@ -149,9 +161,26 @@ public: */ virtual bool isWritable() const = 0; - /* TODO: - bool isFile(); - */ + + /** + * Creates a SeekableReadStream instance corresponding to the file + * referred by this node. This assumes that the node actually refers + * to a readable file. If this is not the case, 0 is returned. + * + * @return pointer to the stream object, 0 in case of a failure + */ + virtual Common::SeekableReadStream *openForReading() = 0; + + /** + * Creates a WriteStream instance corresponding to the file + * referred by this node. This assumes that the node actually refers + * to a readable file. If this is not the case, 0 is returned. + * + * @return pointer to the stream object, 0 in case of a failure + */ + virtual Common::WriteStream *openForWriting() = 0; }; + + #endif //BACKENDS_ABSTRACT_FS_H diff --git a/backends/fs/amigaos4/amigaos4-fs-factory.cpp b/backends/fs/amigaos4/amigaos4-fs-factory.cpp index af843b7c78..2b0b2f1908 100644 --- a/backends/fs/amigaos4/amigaos4-fs-factory.cpp +++ b/backends/fs/amigaos4/amigaos4-fs-factory.cpp @@ -26,8 +26,6 @@ #include "backends/fs/amigaos4/amigaos4-fs-factory.h" #include "backends/fs/amigaos4/amigaos4-fs.cpp" -DECLARE_SINGLETON(AmigaOSFilesystemFactory); - AbstractFilesystemNode *AmigaOSFilesystemFactory::makeRootFileNode() const { return new AmigaOSFilesystemNode(); } @@ -36,7 +34,7 @@ AbstractFilesystemNode *AmigaOSFilesystemFactory::makeCurrentDirectoryFileNode() return new AmigaOSFilesystemNode(); } -AbstractFilesystemNode *AmigaOSFilesystemFactory::makeFileNodePath(const String &path) const { +AbstractFilesystemNode *AmigaOSFilesystemFactory::makeFileNodePath(const Common::String &path) const { return new AmigaOSFilesystemNode(path); } #endif diff --git a/backends/fs/amigaos4/amigaos4-fs-factory.h b/backends/fs/amigaos4/amigaos4-fs-factory.h index 58a7dcd372..03af6e95b9 100644 --- a/backends/fs/amigaos4/amigaos4-fs-factory.h +++ b/backends/fs/amigaos4/amigaos4-fs-factory.h @@ -25,7 +25,6 @@ #ifndef AMIGAOS_FILESYSTEM_FACTORY_H #define AMIGAOS_FILESYSTEM_FACTORY_H -#include "common/singleton.h" #include "backends/fs/fs-factory.h" /** @@ -33,19 +32,11 @@ * * Parts of this class are documented in the base interface class, FilesystemFactory. */ -class AmigaOSFilesystemFactory : public FilesystemFactory, public Common::Singleton<AmigaOSFilesystemFactory> { +class AmigaOSFilesystemFactory : public FilesystemFactory { public: - typedef Common::String String; - virtual AbstractFilesystemNode *makeRootFileNode() const; virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const; - virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const; - -protected: - AmigaOSFilesystemFactory() {}; - -private: - friend class Common::Singleton<SingletonBaseType>; + virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const; }; #endif /*AMIGAOS_FILESYSTEM_FACTORY_H*/ diff --git a/backends/fs/amigaos4/amigaos4-fs.cpp b/backends/fs/amigaos4/amigaos4-fs.cpp index 5bf57ddf34..d517121dc0 100644 --- a/backends/fs/amigaos4/amigaos4-fs.cpp +++ b/backends/fs/amigaos4/amigaos4-fs.cpp @@ -36,8 +36,8 @@ #endif #include "common/util.h" -#include "engines/engine.h" #include "backends/fs/abstract-fs.h" +#include "backends/fs/stdiostream.h" #define ENTER() /* debug(6, "Enter") */ #define LEAVE() /* debug(6, "Leave") */ @@ -52,8 +52,8 @@ const uint32 kExAllBufferSize = 40960; // TODO: is this okay for sure? class AmigaOSFilesystemNode : public AbstractFilesystemNode { protected: BPTR _pFileLock; - String _sDisplayName; - String _sPath; + Common::String _sDisplayName; + Common::String _sPath; bool _bIsDirectory; bool _bIsValid; @@ -74,9 +74,9 @@ public: /** * Creates a AmigaOSFilesystemNode for a given path. * - * @param path String with the path the new node should point to. + * @param path Common::String with the path the new node should point to. */ - AmigaOSFilesystemNode(const String &p); + AmigaOSFilesystemNode(const Common::String &p); /** * FIXME: document this constructor. @@ -96,17 +96,20 @@ public: virtual ~AmigaOSFilesystemNode(); virtual bool exists() const; - virtual String getDisplayName() const { return _sDisplayName; }; - virtual String getName() const { return _sDisplayName; }; - virtual String getPath() const { return _sPath; }; + virtual Common::String getDisplayName() const { return _sDisplayName; }; + virtual Common::String getName() const { return _sDisplayName; }; + virtual Common::String getPath() const { return _sPath; }; virtual bool isDirectory() const { return _bIsDirectory; }; virtual bool isReadable() const; virtual bool isWritable() const; - virtual AbstractFilesystemNode *getChild(const String &n) const; + virtual AbstractFilesystemNode *getChild(const Common::String &n) const; virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; virtual AbstractFilesystemNode *getParent() const; + virtual Common::SeekableReadStream *openForReading(); + virtual Common::WriteStream *openForWriting(); + /** * Creates a list with all the volumes present in the root node. */ @@ -116,7 +119,7 @@ public: /** * Returns the last component of a given path. * - * @param str String containing the path. + * @param str Common::String containing the path. * @return Pointer to the first char of the last component inside str. */ const char *lastPathComponent(const Common::String &str) { @@ -148,10 +151,10 @@ AmigaOSFilesystemNode::AmigaOSFilesystemNode() { LEAVE(); } -AmigaOSFilesystemNode::AmigaOSFilesystemNode(const String &p) { +AmigaOSFilesystemNode::AmigaOSFilesystemNode(const Common::String &p) { ENTER(); - int len = 0, offset = p.size(); + int offset = p.size(); //assert(offset > 0); @@ -161,7 +164,7 @@ AmigaOSFilesystemNode::AmigaOSFilesystemNode(const String &p) { } _sPath = p; - _sDisplayName = lastPathComponent(_sPath); + _sDisplayName = ::lastPathComponent(_sPath); _pFileLock = 0; _bIsDirectory = false; @@ -299,14 +302,14 @@ bool AmigaOSFilesystemNode::exists() const { return nodeExists; } -AbstractFilesystemNode *AmigaOSFilesystemNode::getChild(const String &n) const { +AbstractFilesystemNode *AmigaOSFilesystemNode::getChild(const Common::String &n) const { ENTER(); if (!_bIsDirectory) { debug(6, "Not a directory"); return 0; } - String newPath(_sPath); + Common::String newPath(_sPath); if (_sPath.lastChar() != '/') newPath += '/'; @@ -368,10 +371,10 @@ bool AmigaOSFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, b struct ExAllData *ead = data; do { - if ((mode == FilesystemNode::kListAll) || - (EAD_IS_DRAWER(ead) && (mode == FilesystemNode::kListDirectoriesOnly)) || - (EAD_IS_FILE(ead) && (mode == FilesystemNode::kListFilesOnly))) { - String full_path = _sPath; + if ((mode == Common::FilesystemNode::kListAll) || + (EAD_IS_DRAWER(ead) && (mode == Common::FilesystemNode::kListDirectoriesOnly)) || + (EAD_IS_FILE(ead) && (mode == Common::FilesystemNode::kListFilesOnly))) { + Common::String full_path = _sPath; full_path += (char*)ead->ed_Name; BPTR lock = IDOS->Lock((STRPTR)full_path.c_str(), SHARED_LOCK); @@ -566,4 +569,12 @@ AbstractFSList AmigaOSFilesystemNode::listVolumes() const { return myList; } +Common::SeekableReadStream *AmigaOSFilesystemNode::openForReading() { + return StdioStream::makeFromPath(getPath().c_str(), false); +} + +Common::WriteStream *AmigaOSFilesystemNode::openForWriting() { + return StdioStream::makeFromPath(getPath().c_str(), true); +} + #endif //defined(__amigaos4__) diff --git a/backends/fs/ds/ds-fs-factory.cpp b/backends/fs/ds/ds-fs-factory.cpp index 2eae2f2403..5c8c3f45f8 100644 --- a/backends/fs/ds/ds-fs-factory.cpp +++ b/backends/fs/ds/ds-fs-factory.cpp @@ -45,7 +45,7 @@ AbstractFilesystemNode *DSFilesystemFactory::makeCurrentDirectoryFileNode() cons } } -AbstractFilesystemNode *DSFilesystemFactory::makeFileNodePath(const String &path) const { +AbstractFilesystemNode *DSFilesystemFactory::makeFileNodePath(const Common::String &path) const { if (DS::isGBAMPAvailable()) { return new DS::GBAMPFileSystemNode(path); } else { diff --git a/backends/fs/ds/ds-fs-factory.h b/backends/fs/ds/ds-fs-factory.h index bff21a309d..67e0076b78 100644 --- a/backends/fs/ds/ds-fs-factory.h +++ b/backends/fs/ds/ds-fs-factory.h @@ -35,11 +35,9 @@ */ class DSFilesystemFactory : public FilesystemFactory, public Common::Singleton<DSFilesystemFactory> { public: - typedef Common::String String; - virtual AbstractFilesystemNode *makeRootFileNode() const; virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const; - virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const; + virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const; protected: DSFilesystemFactory() {}; diff --git a/backends/fs/ds/ds-fs.cpp b/backends/fs/ds/ds-fs.cpp index cffe4c118d..911702316d 100644 --- a/backends/fs/ds/ds-fs.cpp +++ b/backends/fs/ds/ds-fs.cpp @@ -24,6 +24,7 @@ #include "common/util.h" //#include <NDS/ARM9/console.h> //basic print funcionality #include "backends/fs/ds/ds-fs.h" +#include "backends/fs/stdiostream.h" #include "dsmain.h" #include "fat/gba_nds_fat.h" @@ -55,7 +56,7 @@ DSFileSystemNode::DSFileSystemNode() { } } -DSFileSystemNode::DSFileSystemNode(const String& path) { +DSFileSystemNode::DSFileSystemNode(const Common::String& path) { // consolePrintf("--%s ",path.c_str()); char disp[128]; @@ -70,7 +71,7 @@ DSFileSystemNode::DSFileSystemNode(const String& path) { strcpy(disp, pathStr + lastSlash + 1); - _displayName = String(disp); + _displayName = Common::String(disp); _path = path; // _isValid = true; // _isDirectory = false; @@ -98,7 +99,7 @@ DSFileSystemNode::DSFileSystemNode(const String& path) { // consolePrintf("%s - Found: %d, Dir: %d\n", pathStr, _isValid, _isDirectory); } -DSFileSystemNode::DSFileSystemNode(const String& path, bool isDir) { +DSFileSystemNode::DSFileSystemNode(const Common::String& path, bool isDir) { // consolePrintf("--%s ",path.c_str()); char disp[128]; @@ -112,7 +113,7 @@ DSFileSystemNode::DSFileSystemNode(const String& path, bool isDir) { strcpy(disp, pathStr + lastSlash + 1); - _displayName = String(disp); + _displayName = Common::String(disp); _path = path; _isValid = true; _isDirectory = isDir; @@ -167,10 +168,10 @@ bool DSFileSystemNode::getChildren(AbstractFSList &dirList, ListMode mode, bool _zipFile->getFileName(n); // consolePrintf("file: %s\n", n); - if ( (_zipFile->isDirectory() && ((mode == FilesystemNode::kListDirectoriesOnly) || (mode == FilesystemNode::kListAll)) ) - || (!_zipFile->isDirectory() && ((mode == FilesystemNode::kListFilesOnly) || (mode == FilesystemNode::kListAll)) ) ) + if ( (_zipFile->isDirectory() && ((mode == Common::FilesystemNode::kListDirectoriesOnly) || (mode == Common::FilesystemNode::kListAll)) ) + || (!_zipFile->isDirectory() && ((mode == Common::FilesystemNode::kListFilesOnly) || (mode == Common::FilesystemNode::kListAll)) ) ) { - DSFileSystemNode* dsfsn = new DSFileSystemNode("ds:/" + String(n), _zipFile->isDirectory()); + DSFileSystemNode* dsfsn = new DSFileSystemNode("ds:/" + Common::String(n), _zipFile->isDirectory()); dsfsn->_isDirectory = _zipFile->isDirectory(); dirList.push_back((dsfsn)); } @@ -195,7 +196,7 @@ AbstractFilesystemNode* DSFileSystemNode::getParent() const { } } - p = new DSFileSystemNode(String(path, lastSlash)); + p = new DSFileSystemNode(Common::String(path, lastSlash)); ((DSFileSystemNode *) (p))->_isDirectory = true; } else { p = new DSFileSystemNode(); @@ -204,6 +205,14 @@ AbstractFilesystemNode* DSFileSystemNode::getParent() const { return p; } +Common::SeekableReadStream *DSFileSystemNode::openForReading() { + return StdioStream::makeFromPath(getPath().c_str(), false); +} + +Common::WriteStream *DSFileSystemNode::openForWriting() { + return StdioStream::makeFromPath(getPath().c_str(), true); +} + ////////////////////////////////////////////////////////////////////////// // GBAMPFileSystemNode - File system using GBA Movie Player and CF card // ////////////////////////////////////////////////////////////////////////// @@ -216,7 +225,7 @@ GBAMPFileSystemNode::GBAMPFileSystemNode() { _path = "mp:/"; } -GBAMPFileSystemNode::GBAMPFileSystemNode(const String& path) { +GBAMPFileSystemNode::GBAMPFileSystemNode(const Common::String& path) { // consolePrintf("'%s'",path.c_str()); char disp[128]; @@ -245,13 +254,13 @@ GBAMPFileSystemNode::GBAMPFileSystemNode(const String& path) { } // consolePrintf("Path: %s (%d)\n", check, success); - _displayName = String(disp); + _displayName = Common::String(disp); _path = path; _isValid = success == FT_FILE; _isDirectory = success == FT_DIR; } -GBAMPFileSystemNode::GBAMPFileSystemNode(const String& path, bool isDirectory) { +GBAMPFileSystemNode::GBAMPFileSystemNode(const Common::String& path, bool isDirectory) { // consolePrintf("'%s'",path.c_str()); char disp[128]; @@ -265,7 +274,7 @@ GBAMPFileSystemNode::GBAMPFileSystemNode(const String& path, bool isDirectory) { strcpy(disp, pathStr + lastSlash + 1); - _displayName = String(disp); + _displayName = Common::String(disp); _path = path; _isValid = true; _isDirectory = isDirectory; @@ -313,8 +322,8 @@ bool GBAMPFileSystemNode::getChildren(AbstractFSList& dirList, ListMode mode, bo while (entryType != TYPE_NO_MORE) { - if ( ((entryType == TYPE_DIR) && ((mode == FilesystemNode::kListDirectoriesOnly) || (mode == FilesystemNode::kListAll))) - || ((entryType == TYPE_FILE) && ((mode == FilesystemNode::kListFilesOnly) || (mode == FilesystemNode::kListAll))) ) { + if ( ((entryType == TYPE_DIR) && ((mode == Common::FilesystemNode::kListDirectoriesOnly) || (mode == Common::FilesystemNode::kListAll))) + || ((entryType == TYPE_FILE) && ((mode == Common::FilesystemNode::kListFilesOnly) || (mode == Common::FilesystemNode::kListAll))) ) { GBAMPFileSystemNode* dsfsn; consolePrintf("Fname: %s\n", fname); @@ -322,9 +331,9 @@ bool GBAMPFileSystemNode::getChildren(AbstractFSList& dirList, ListMode mode, bo if (strcmp(fname, ".") && strcmp(fname, "..")) { if (!strcmp(path, "/")) { - dsfsn = new GBAMPFileSystemNode("mp:" + String(path) + String(fname), entryType == TYPE_DIR); + dsfsn = new GBAMPFileSystemNode("mp:" + Common::String(path) + Common::String(fname), entryType == TYPE_DIR); } else { - dsfsn = new GBAMPFileSystemNode("mp:" + String(path) + String("/") + String(fname), entryType == TYPE_DIR); + dsfsn = new GBAMPFileSystemNode("mp:" + Common::String(path) + Common::String("/") + Common::String(fname), entryType == TYPE_DIR); } // dsfsn->_isDirectory = entryType == DIR; @@ -358,7 +367,7 @@ AbstractFilesystemNode* GBAMPFileSystemNode::getParent() const { } } - p = new GBAMPFileSystemNode(String(path, lastSlash)); + p = new GBAMPFileSystemNode(Common::String(path, lastSlash)); p->_isDirectory = true; } else { p = new GBAMPFileSystemNode(); @@ -367,6 +376,14 @@ AbstractFilesystemNode* GBAMPFileSystemNode::getParent() const { return p; } +Common::SeekableReadStream *GBAMPFileSystemNode::openForReading() { + return StdioStream::makeFromPath(getPath().c_str(), false); +} + +Common::WriteStream *GBAMPFileSystemNode::openForWriting() { + return StdioStream::makeFromPath(getPath().c_str(), true); +} + // Stdio replacements #define MAX_FILE_HANDLES 32 @@ -399,6 +416,7 @@ FILE* std_fopen(const char* name, const char* mode) { if (DS::isGBAMPAvailable()) { FAT_chdir("/"); + // Turn all back slashes into forward slashes for gba_nds_fat char* p = realName; while (*p) { if (*p == '\\') *p = '/'; @@ -422,8 +440,12 @@ FILE* std_fopen(const char* name, const char* mode) { // Allocate a file handle int r = 0; - while (handle[r].used) r++; + while (handle[r].used) { + r++; + assert(r < MAX_FILE_HANDLES); + } +#ifdef GBA_SRAM_SAVE if (strchr(mode, 'w')) { // consolePrintf("Writing %s\n", realName); handle[r].sramFile = (DSSaveFile *) DSSaveFileManager::instance()->openSavefile(realName, true); @@ -431,6 +453,7 @@ FILE* std_fopen(const char* name, const char* mode) { // consolePrintf("Reading %s\n", realName); handle[r].sramFile = (DSSaveFile *) DSSaveFileManager::instance()->openSavefile(realName, false); } +#endif if (handle[r].sramFile) { handle[r].used = true; @@ -512,69 +535,6 @@ size_t std_fread(const void* ptr, size_t size, size_t numItems, FILE* handle) { return bytes / size; } return numItems; - -/* int item = 0; - u8* data = (u8 *) ptr; - while ((item < numItems) && (!FAT_feof((FAT_FILE *) handle))) { - - - int bytes = 0; - while ((bytes < size) && (!FAT_feof((FAT_FILE *) handle))) { - *data++ = FAT_fgetc((FAT_FILE *) handle); - bytes++; - } - - item++; - - } - - return item; -*/ - int items = 0; - - //for (int r = 0; r < numItems; r++) { - if (!std_feof(handle)) { -/* for (int t = 0; t < size; t++) { - if (feof(handle)) eof = true; - *(((char *) (ptr)) + r * size + t) = getc(handle); - }*/ - int left = size * numItems; - int bytesRead = -1; - - while ((left > 0) && (!FAT_feof((FAT_FILE *) handle))) { - int amount = left > 8192? 8192: left; -// do { - bytesRead = FAT_fread((void *) ptr, 1, amount, (FAT_FILE *) handle); -/* if (bytesRead == 0) { - consolePrintf("Pos:%d items:%d num:%d amount:%d read:%d\n", ftell(handle), items, numItems, amount, bytesRead); - left++; - - int pos = ftell(handle); - - fseek(handle, 0, SEEK_SET); - int c = getc(handle); - fseek(handle, pos - 1024, SEEK_SET); - fread(ptr, 1024, 1, handle); - swiWaitForVBlank(); - //while (true); - } - - } while (bytesRead == 0); -*/ - left -= bytesRead; - ptr = ((char *) (ptr)) + bytesRead; - } - - items = numItems - (left / size); - -// FAT_fread((void *) ptr, size, 1, ((int) (handle)) - 1); -// ptr = ((char *) (ptr)) + size; - } -// } - -// consolePrintf("...done %d \n", items) - - return items; } if (handle->sramFile) { @@ -641,10 +601,6 @@ size_t std_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle) { } } -void std_fprintf(FILE* handle, const char* fmt, ...) { - consolePrintf(fmt); -} - bool std_feof(FILE* handle) { // consolePrintf("feof "); @@ -660,42 +616,10 @@ bool std_feof(FILE* handle) { return handle->pos >= handle->size; } -void std_fflush(FILE* handle) { +int std_fflush(FILE* handle) { //FIXME: not implemented? // consolePrintf("fflush "); -} - -char* std_fgets(char* str, int size, FILE* file) { -// consolePrintf("fgets file=%d ", file); - - if (DS::isGBAMPAvailable()) { - char* s = str; - while ((*s++ = std_getc(file)) >= 32) { -// consolePrintf("%d ", *s); - } - *s = 0; - -// consolePrintf("Read:%s\n", str); - - return str; - } - - if (file->sramFile) { - file->pos--; - int p = -1; - do { - file->pos++; - p++; - file->sramFile->read((char *) &str[p], 1); -// consolePrintf("%d,", str[p]); - } while ((str[p] >= 32) && (!std_feof(file)) && (p < size)); - str[p + 1] = 0; - file->pos++; -// consolePrintf("Read:%s\n", str); - return str; - } - - return NULL; + return 0; } long int std_ftell(FILE* handle) { @@ -731,92 +655,20 @@ int std_fseek(FILE* handle, long int offset, int whence) { return 0; } -void std_clearerr(FILE* handle) { +int std_ferror(FILE* handle) { //FIXME: not implemented? -// consolePrintf("clearerr "); -} - -int std_getc(FILE* handle) { - if (DS::isGBAMPAvailable()) { - char c; - FAT_fread(&c, 1, 1, (FAT_FILE *) handle); - - return c; - } - -// consolePrintf("fgetc "); - return 0; // Not supported yet +// consolePrintf("ferror "); + return 0; } -char* std_getcwd(char* dir, int dunno) { -// consolePrintf("getcwd "); - dir[0] = '\0'; - return dir; // Not supported yet +void std_clearerr(FILE* handle) { + //FIXME: not implemented? +// consolePrintf("clearerr "); } -void std_cwd(char* dir) { - char buffer[128]; - strcpy(buffer, dir); - char* realName = buffer; - - if (DS::isGBAMPAvailable()) { - if ((strlen(dir) >= 4) && (dir[0] == 'm') && (dir[1] == 'p') && (dir[2] == ':') && (dir[3] == '/')) { - realName += 4; - } - - // consolePrintf("Real cwd:%d\n", realName); - - char* p = realName; - while (*p) { - if (*p == '\\') *p = '/'; - p++; - } - - // consolePrintf("Real cwd:%d\n", realName); - FAT_chdir(realName); - } else { - if ((strlen(dir) >= 4) && (dir[0] == 'd') && (dir[1] == 's') && (dir[2] == ':') && (dir[3] == '/')) { - realName += 4; - } - - char* p = realName; - while (*p) { - if (*p == '\\') *p = '/'; - p++; - } - - strcpy(currentDir, realName); - if (*(currentDir + strlen(currentDir) - 1) == '/') { - *(currentDir + strlen(currentDir) - 1) = '\0'; - } -// consolePrintf("CWD: %s\n", currentDir); - } +void std_fprintf(FILE* handle, const char* fmt, ...) { + consolePrintf(fmt); } -int std_ferror(FILE* handle) { - return 0; -} } // namespace DS - -/** - * Returns the last component of a given path. - * - * Examples: - * /foo/bar.txt would return /bar.txt - * /foo/bar/ would return /bar/ - * - * @param str String containing the path. - * @return Pointer to the first char of the last component inside str. - */ -const char *lastPathComponent(const Common::String &str) { - const char *start = str.c_str(); - const char *cur = start + str.size() - 2; - - while (cur >= start && *cur != '/' && *cur != '\\') { - --cur; - } - - return cur + 1; -} - diff --git a/backends/fs/ds/ds-fs.h b/backends/fs/ds/ds-fs.h index 9ac453aca9..36e7bc9824 100644 --- a/backends/fs/ds/ds-fs.h +++ b/backends/fs/ds/ds-fs.h @@ -41,12 +41,10 @@ namespace DS { */ class DSFileSystemNode : public AbstractFilesystemNode { protected: - typedef class Common::String String; - static ZipFile* _zipFile; - String _displayName; - String _path; + Common::String _displayName; + Common::String _path; bool _isDirectory; bool _isValid; @@ -61,7 +59,7 @@ public: * * @param path String with the path the new node should point to. */ - DSFileSystemNode(const String &path); + DSFileSystemNode(const Common::String &path); /** * Creates a DSFilesystemNode for a given path. @@ -69,7 +67,7 @@ public: * @param path String with the path the new node should point to. * @param path true if path is a directory, false otherwise. */ - DSFileSystemNode(const String& path, bool isDir); + DSFileSystemNode(const Common::String& path, bool isDir); /** * Copy constructor. @@ -77,9 +75,9 @@ public: DSFileSystemNode(const DSFileSystemNode *node); virtual bool exists() const { return true; } //FIXME: this is just a stub - virtual String getDisplayName() const { return _displayName; } - virtual String getName() const { return _displayName; } - virtual String getPath() const { return _path; } + virtual Common::String getDisplayName() const { return _displayName; } + virtual Common::String getName() const { return _displayName; } + virtual Common::String getPath() const { return _path; } virtual bool isDirectory() const { return _isDirectory; } virtual bool isReadable() const { return true; } //FIXME: this is just a stub virtual bool isWritable() const { return true; } //FIXME: this is just a stub @@ -89,9 +87,12 @@ public: */ virtual AbstractFilesystemNode *clone() const { return new DSFileSystemNode(this); } virtual AbstractFilesystemNode *getChild(const Common::String& name) const; - virtual bool getChildren(AbstractFSList &list, ListMode mode = FilesystemNode::kListDirectoriesOnly, bool hidden = false) const; + virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; virtual AbstractFilesystemNode *getParent() const; + virtual Common::SeekableReadStream *openForReading(); + virtual Common::WriteStream *openForWriting(); + /** * Returns the zip file this node points to. * TODO: check this documentation. @@ -107,10 +108,8 @@ public: */ class GBAMPFileSystemNode : public AbstractFilesystemNode { protected: - typedef class Common::String String; - - String _displayName; - String _path; + Common::String _displayName; + Common::String _path; bool _isDirectory; bool _isValid; @@ -125,7 +124,7 @@ public: * * @param path String with the path the new node should point to. */ - GBAMPFileSystemNode(const String &path); + GBAMPFileSystemNode(const Common::String &path); /** * Creates a DSFilesystemNode for a given path. @@ -133,7 +132,7 @@ public: * @param path String with the path the new node should point to. * @param path true if path is a directory, false otherwise. */ - GBAMPFileSystemNode(const String &path, bool isDirectory); + GBAMPFileSystemNode(const Common::String &path, bool isDirectory); /** * Copy constructor. @@ -141,9 +140,9 @@ public: GBAMPFileSystemNode(const GBAMPFileSystemNode *node); virtual bool exists() const { return _isValid || _isDirectory; } - virtual String getDisplayName() const { return _displayName; } - virtual String getName() const { return _displayName; } - virtual String getPath() const { return _path; } + virtual Common::String getDisplayName() const { return _displayName; } + virtual Common::String getName() const { return _displayName; } + virtual Common::String getPath() const { return _path; } virtual bool isDirectory() const { return _isDirectory; } virtual bool isReadable() const { return true; } //FIXME: this is just a stub virtual bool isWritable() const { return true; } //FIXME: this is just a stub @@ -153,8 +152,11 @@ public: */ virtual AbstractFilesystemNode *clone() const { return new GBAMPFileSystemNode(this); } virtual AbstractFilesystemNode *getChild(const Common::String& name) const; - virtual bool getChildren(AbstractFSList &list, ListMode mode = FilesystemNode::kListDirectoriesOnly, bool hidden = false) const; + virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; virtual AbstractFilesystemNode *getParent() const; + + virtual Common::SeekableReadStream *openForReading(); + virtual Common::WriteStream *openForWriting(); }; struct fileHandle { @@ -179,15 +181,14 @@ struct fileHandle { // Please do not remove any of these prototypes that appear not to be required. FILE* std_fopen(const char* name, const char* mode); void std_fclose(FILE* handle); -int std_getc(FILE* handle); size_t std_fread(const void* ptr, size_t size, size_t numItems, FILE* handle); size_t std_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle); bool std_feof(FILE* handle); long int std_ftell(FILE* handle); int std_fseek(FILE* handle, long int offset, int whence); void std_clearerr(FILE* handle); -void std_cwd(char* dir); -void std_fflush(FILE* handle); +int std_fflush(FILE* handle); +int std_ferror(FILE* handle); } //namespace DS diff --git a/backends/fs/palmos/palmos-fs-factory.cpp b/backends/fs/palmos/palmos-fs-factory.cpp index 8699a9788b..bbc1639897 100644 --- a/backends/fs/palmos/palmos-fs-factory.cpp +++ b/backends/fs/palmos/palmos-fs-factory.cpp @@ -36,7 +36,7 @@ AbstractFilesystemNode *PalmOSFilesystemFactory::makeCurrentDirectoryFileNode() return new PalmOSFilesystemNode(); } -AbstractFilesystemNode *PalmOSFilesystemFactory::makeFileNodePath(const String &path) const { +AbstractFilesystemNode *PalmOSFilesystemFactory::makeFileNodePath(const Common::String &path) const { return new PalmOSFilesystemNode(path); } #endif diff --git a/backends/fs/palmos/palmos-fs-factory.h b/backends/fs/palmos/palmos-fs-factory.h index 3ea8b5fe47..f778aa89ef 100644 --- a/backends/fs/palmos/palmos-fs-factory.h +++ b/backends/fs/palmos/palmos-fs-factory.h @@ -35,11 +35,9 @@ */ class PalmOSFilesystemFactory : public FilesystemFactory, public Common::Singleton<PalmOSFilesystemFactory> { public: - typedef Common::String String; - virtual AbstractFilesystemNode *makeRootFileNode() const; virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const; - virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const; + virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const; protected: PalmOSFilesystemFactory() {}; diff --git a/backends/fs/palmos/palmos-fs.cpp b/backends/fs/palmos/palmos-fs.cpp index 5edb6c2d26..7c415aa320 100644 --- a/backends/fs/palmos/palmos-fs.cpp +++ b/backends/fs/palmos/palmos-fs.cpp @@ -28,6 +28,7 @@ #include "globals.h" #include "backends/fs/abstract-fs.h" +#include "backends/fs/stdiostream.h" /** * Implementation of the ScummVM file system API based on PalmOS VFS API. @@ -36,8 +37,8 @@ */ class PalmOSFilesystemNode : public AbstractFilesystemNode { protected: - String _displayName; - String _path; + Common::String _displayName; + Common::String _path; bool _isDirectory; bool _isValid; bool _isPseudoRoot; @@ -51,22 +52,25 @@ public: /** * Creates a POSIXFilesystemNode for a given path. * - * @param path String with the path the new node should point to. + * @param path Common::String with the path the new node should point to. */ - PalmOSFilesystemNode(const String &p); + PalmOSFilesystemNode(const Common::String &p); virtual bool exists() const { return _isValid; } - virtual String getDisplayName() const { return _displayName; } - virtual String getName() const { return _displayName; } - virtual String getPath() const { return _path; } + virtual Common::String getDisplayName() const { return _displayName; } + virtual Common::String getName() const { return _displayName; } + virtual Common::String getPath() const { return _path; } virtual bool isDirectory() const { return _isDirectory; } virtual bool isReadable() const { return true; } //FIXME: this is just a stub virtual bool isWritable() const { return true; } //FIXME: this is just a stub - virtual AbstractFilesystemNode *getChild(const String &n) const; + virtual AbstractFilesystemNode *getChild(const Common::String &n) const; virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; virtual AbstractFilesystemNode *getParent() const; + virtual Common::SeekableReadStream *openForReading(); + virtual Common::WriteStream *openForWriting(); + private: /** * Adds a single WindowsFilesystemNode to a given list. @@ -74,44 +78,20 @@ private: * * @param list List to put the file entry node in. * @param mode Mode to use while adding the file entry to the list. - * @param base String with the directory being listed. + * @param base Common::String with the directory being listed. * @param find_data Describes a file that the FindFirstFile, FindFirstFileEx, or FindNextFile functions find. */ static void addFile(AbstractFSList &list, ListMode mode, const Char *base, FileInfoType* find_data); }; -/** - * Returns the last component of a given path. - * - * Examples: - * /foo/bar.txt would return /bar.txt - * /foo/bar/ would return /bar/ - * - * @param str String containing the path. - * @return Pointer to the first char of the last component inside str. - */ -const char *lastPathComponent(const Common::String &str) { - if(str.empty()) - return ""; - - const char *start = str.c_str(); - const char *cur = start + str.size() - 2; - - while (cur >= start && *cur != '/') { - --cur; - } - - return cur + 1; -} - void PalmOSFilesystemNode::addFile(AbstractFSList &list, ListMode mode, const char *base, FileInfoType* find_data) { PalmOSFilesystemNode entry; bool isDir; isDir = (find_data->attributes & vfsFileAttrDirectory); - if ((!isDir && mode == FilesystemNode::kListDirectoriesOnly) || - (isDir && mode == FilesystemNode::kListFilesOnly)) + if ((!isDir && mode == Common::FilesystemNode::kListDirectoriesOnly) || + (isDir && mode == Common::FilesystemNode::kListFilesOnly)) return; entry._isDirectory = isDir; @@ -136,9 +116,9 @@ PalmOSFilesystemNode::PalmOSFilesystemNode() { _isPseudoRoot = false; } -PalmOSFilesystemNode::PalmOSFilesystemNode(const String &p) { +PalmOSFilesystemNode::PalmOSFilesystemNode(const Common::String &p) { _path = p; - _displayName = lastPathComponent(_path); + _displayName = lastPathComponent(_path, '/'); UInt32 attr; FileRef handle; @@ -159,10 +139,10 @@ PalmOSFilesystemNode::PalmOSFilesystemNode(const String &p) { _isPseudoRoot = false; } -AbstractFilesystemNode *PalmOSFilesystemNode::getChild(const String &n) const { +AbstractFilesystemNode *PalmOSFilesystemNode::getChild(const Common::String &n) const { assert(_isDirectory); - String newPath(_path); + Common::String newPath(_path); if (_path.lastChar() != '/') newPath += '/'; newPath += n; @@ -215,17 +195,25 @@ AbstractFilesystemNode *PalmOSFilesystemNode::getParent() const { if (!_isPseudoRoot) { const char *start = _path.c_str(); - const char *end = lastPathComponent(_path); + const char *end = lastPathComponent(_path, '/'); p = new PalmOSFilesystemNode(); - p->_path = String(start, end - start); + p->_path = Common::String(start, end - start); p->_isValid = true; p->_isDirectory = true; - p->_displayName = lastPathComponent(p->_path); + p->_displayName = lastPathComponent(p->_path, '/'); p->_isPseudoRoot =(p->_path == "/"); } return p; } +Common::SeekableReadStream *PalmOSFilesystemNode::openForReading() { + return StdioStream::makeFromPath(getPath().c_str(), false); +} + +Common::WriteStream *PalmOSFilesystemNode::openForWriting() { + return StdioStream::makeFromPath(getPath().c_str(), true); +} + #endif // PALMOS_MODE diff --git a/backends/fs/posix/posix-fs-factory.cpp b/backends/fs/posix/posix-fs-factory.cpp index 0a1160ff8f..cbfb69b76a 100644 --- a/backends/fs/posix/posix-fs-factory.cpp +++ b/backends/fs/posix/posix-fs-factory.cpp @@ -26,19 +26,18 @@ #include "backends/fs/posix/posix-fs-factory.h" #include "backends/fs/posix/posix-fs.cpp" -DECLARE_SINGLETON(POSIXFilesystemFactory); - AbstractFilesystemNode *POSIXFilesystemFactory::makeRootFileNode() const { - return new POSIXFilesystemNode(); + return new POSIXFilesystemNode("/"); } AbstractFilesystemNode *POSIXFilesystemFactory::makeCurrentDirectoryFileNode() const { char buf[MAXPATHLEN]; getcwd(buf, MAXPATHLEN); - return new POSIXFilesystemNode(buf, true); + return new POSIXFilesystemNode(buf); } -AbstractFilesystemNode *POSIXFilesystemFactory::makeFileNodePath(const String &path) const { - return new POSIXFilesystemNode(path, true); +AbstractFilesystemNode *POSIXFilesystemFactory::makeFileNodePath(const Common::String &path) const { + assert(!path.empty()); + return new POSIXFilesystemNode(path); } #endif diff --git a/backends/fs/posix/posix-fs-factory.h b/backends/fs/posix/posix-fs-factory.h index d8eecda6ef..c697679814 100644 --- a/backends/fs/posix/posix-fs-factory.h +++ b/backends/fs/posix/posix-fs-factory.h @@ -25,7 +25,6 @@ #ifndef POSIX_FILESYSTEM_FACTORY_H #define POSIX_FILESYSTEM_FACTORY_H -#include "common/singleton.h" #include "backends/fs/fs-factory.h" /** @@ -33,19 +32,10 @@ * * Parts of this class are documented in the base interface class, FilesystemFactory. */ -class POSIXFilesystemFactory : public FilesystemFactory, public Common::Singleton<POSIXFilesystemFactory> { -public: - typedef Common::String String; - +class POSIXFilesystemFactory : public FilesystemFactory { virtual AbstractFilesystemNode *makeRootFileNode() const; virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const; - virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const; - -protected: - POSIXFilesystemFactory() {}; - -private: - friend class Common::Singleton<SingletonBaseType>; + virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const; }; #endif /*POSIX_FILESYSTEM_FACTORY_H*/ diff --git a/backends/fs/posix/posix-fs.cpp b/backends/fs/posix/posix-fs.cpp index 5cde32c851..8dca78d82a 100644 --- a/backends/fs/posix/posix-fs.cpp +++ b/backends/fs/posix/posix-fs.cpp @@ -24,85 +24,20 @@ #if defined(UNIX) -#include "backends/fs/abstract-fs.h" +#include "backends/fs/posix/posix-fs.h" +#include "backends/fs/stdiostream.h" +#include "common/algorithm.h" -#ifdef MACOSX -#include <sys/types.h> -#endif #include <sys/param.h> #include <sys/stat.h> #include <dirent.h> #include <stdio.h> -#include <unistd.h> -/** - * Implementation of the ScummVM file system API based on POSIX. - * - * Parts of this class are documented in the base interface class, AbstractFilesystemNode. - */ -class POSIXFilesystemNode : public AbstractFilesystemNode { -protected: - String _displayName; - String _path; - bool _isDirectory; - bool _isValid; - -public: - /** - * Creates a POSIXFilesystemNode with the root node as path. - */ - POSIXFilesystemNode(); - - /** - * Creates a POSIXFilesystemNode for a given path. - * - * @param path String with the path the new node should point to. - * @param verify true if the isValid and isDirectory flags should be verified during the construction. - */ - POSIXFilesystemNode(const String &path, bool verify); - - virtual bool exists() const { return access(_path.c_str(), F_OK) == 0; } - virtual String getDisplayName() const { return _displayName; } - virtual String getName() const { return _displayName; } - virtual String getPath() const { return _path; } - virtual bool isDirectory() const { return _isDirectory; } - virtual bool isReadable() const { return access(_path.c_str(), R_OK) == 0; } - virtual bool isWritable() const { return access(_path.c_str(), W_OK) == 0; } - - virtual AbstractFilesystemNode *getChild(const String &n) const; - virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; - virtual AbstractFilesystemNode *getParent() const; - -private: - /** - * Tests and sets the _isValid and _isDirectory flags, using the stat() function. - */ - virtual void setFlags(); -}; - -/** - * Returns the last component of a given path. - * - * Examples: - * /foo/bar.txt would return /bar.txt - * /foo/bar/ would return /bar/ - * - * @param str String containing the path. - * @return Pointer to the first char of the last component inside str. - */ -const char *lastPathComponent(const Common::String &str) { - if(str.empty()) - return ""; - - const char *start = str.c_str(); - const char *cur = start + str.size() - 2; - - while (cur >= start && *cur != '/') { - --cur; - } +#ifdef __OS2__ +#define INCL_DOS +#include <os2.h> +#endif - return cur + 1; -} void POSIXFilesystemNode::setFlags() { struct stat st; @@ -111,15 +46,7 @@ void POSIXFilesystemNode::setFlags() { _isDirectory = _isValid ? S_ISDIR(st.st_mode) : false; } -POSIXFilesystemNode::POSIXFilesystemNode() { - // The root dir. - _path = "/"; - _displayName = _path; - _isValid = true; - _isDirectory = true; -} - -POSIXFilesystemNode::POSIXFilesystemNode(const String &p, bool verify) { +POSIXFilesystemNode::POSIXFilesystemNode(const Common::String &p) { assert(p.size() > 0); // Expand "~/" to the value of the HOME env variable @@ -134,30 +61,85 @@ POSIXFilesystemNode::POSIXFilesystemNode(const String &p, bool verify) { } else { _path = p; } - - _displayName = lastPathComponent(_path); - - if (verify) { - setFlags(); + +#ifdef __OS2__ + // On OS/2, 'X:/' is a root of drive X, so we should not remove that last + // slash. + if (!(_path.size() == 3 && _path.hasSuffix(":/"))) +#endif + // Normalize the path (that is, remove unneeded slashes etc.) + _path = Common::normalizePath(_path, '/'); + _displayName = Common::lastPathComponent(_path, '/'); + + // TODO: should we turn relative paths into absolute ones? + // Pro: Ensures the "getParent" works correctly even for relative dirs. + // Contra: The user may wish to use (and keep!) relative paths in his + // config file, and converting relative to absolute paths may hurt him... + // + // An alternative approach would be to change getParent() to work correctly + // if "_path" is the empty string. +#if 0 + if (!_path.hasPrefix("/")) { + char buf[MAXPATHLEN+1]; + getcwd(buf, MAXPATHLEN); + strcat(buf, "/"); + _path = buf + _path; } +#endif + // TODO: Should we enforce that the path is absolute at this point? + //assert(_path.hasPrefix("/")); + + setFlags(); } -AbstractFilesystemNode *POSIXFilesystemNode::getChild(const String &n) const { - // FIXME: Pretty lame implementation! We do no error checking to speak - // of, do not check if this is a special node, etc. +AbstractFilesystemNode *POSIXFilesystemNode::getChild(const Common::String &n) const { + assert(!_path.empty()); assert(_isDirectory); + + // Make sure the string contains no slashes + assert(!n.contains('/')); - String newPath(_path); + // We assume here that _path is already normalized (hence don't bother to call + // Common::normalizePath on the final path). + Common::String newPath(_path); if (_path.lastChar() != '/') newPath += '/'; newPath += n; - return new POSIXFilesystemNode(newPath, true); + return makeNode(newPath); } bool POSIXFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool hidden) const { assert(_isDirectory); +#ifdef __OS2__ + if (_path == "/") { + // Special case for the root dir: List all DOS drives + ULONG ulDrvNum; + ULONG ulDrvMap; + + DosQueryCurrentDisk(&ulDrvNum, &ulDrvMap); + + for (int i = 0; i < 26; i++) { + if (ulDrvMap & 1) { + char drive_root[] = "A:/"; + drive_root[0] += i; + + POSIXFilesystemNode *entry = new POSIXFilesystemNode(); + entry->_isDirectory = true; + entry->_isValid = true; + entry->_path = drive_root; + entry->_displayName = "[" + Common::String(drive_root, 2) + "]"; + myList.push_back(entry); + } + + ulDrvMap >>= 1; + } + + return true; + } +#endif + DIR *dirp = opendir(_path.c_str()); struct dirent *dp; @@ -175,12 +157,12 @@ bool POSIXFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, boo continue; } - String newPath(_path); - if (newPath.lastChar() != '/') - newPath += '/'; - newPath += dp->d_name; - - POSIXFilesystemNode entry(newPath, false); + // Start with a clone of this node, with the correct path set + POSIXFilesystemNode entry(*this); + entry._displayName = dp->d_name; + if (_path.lastChar() != '/') + entry._path += '/'; + entry._path += entry._displayName; #if defined(SYSTEM_NOT_SUPPORTING_D_TYPE) /* TODO: d_type is not part of POSIX, so it might not be supported @@ -215,13 +197,10 @@ bool POSIXFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, boo continue; // Honor the chosen mode - if ((mode == FilesystemNode::kListFilesOnly && entry._isDirectory) || - (mode == FilesystemNode::kListDirectoriesOnly && !entry._isDirectory)) + if ((mode == Common::FilesystemNode::kListFilesOnly && entry._isDirectory) || + (mode == Common::FilesystemNode::kListDirectoriesOnly && !entry._isDirectory)) continue; - if (entry._isDirectory) - entry._path += "/"; - myList.push_back(new POSIXFilesystemNode(entry)); } closedir(dirp); @@ -231,12 +210,39 @@ bool POSIXFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, boo AbstractFilesystemNode *POSIXFilesystemNode::getParent() const { if (_path == "/") - return 0; + return 0; // The filesystem root has no parent + +#ifdef __OS2__ + if (_path.size() == 3 && _path.hasSuffix(":/")) + // This is a root directory of a drive + return makeNode("/"); // return a virtual root for a list of drives +#endif const char *start = _path.c_str(); - const char *end = lastPathComponent(_path); + const char *end = start + _path.size(); + + // Strip of the last component. We make use of the fact that at this + // point, _path is guaranteed to be normalized + while (end > start && *(end-1) != '/') + end--; + + if (end == start) { + // This only happens if we were called with a relative path, for which + // there simply is no parent. + // TODO: We could also resolve this by assuming that the parent is the + // current working directory, and returning a node referring to that. + return 0; + } + + return makeNode(Common::String(start, end)); +} + +Common::SeekableReadStream *POSIXFilesystemNode::openForReading() { + return StdioStream::makeFromPath(getPath().c_str(), false); +} - return new POSIXFilesystemNode(String(start, end - start), true); +Common::WriteStream *POSIXFilesystemNode::openForWriting() { + return StdioStream::makeFromPath(getPath().c_str(), true); } #endif //#if defined(UNIX) diff --git a/backends/fs/posix/posix-fs.h b/backends/fs/posix/posix-fs.h new file mode 100644 index 0000000000..e09e433e05 --- /dev/null +++ b/backends/fs/posix/posix-fs.h @@ -0,0 +1,86 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + */ + +#ifndef POSIX_FILESYSTEM_H +#define POSIX_FILESYSTEM_H + +#include "backends/fs/abstract-fs.h" + +#ifdef MACOSX +#include <sys/types.h> +#endif +#include <unistd.h> + +/** + * Implementation of the ScummVM file system API based on POSIX. + * + * Parts of this class are documented in the base interface class, AbstractFilesystemNode. + */ +class POSIXFilesystemNode : public AbstractFilesystemNode { +protected: + Common::String _displayName; + Common::String _path; + bool _isDirectory; + bool _isValid; + + virtual AbstractFilesystemNode *makeNode(const Common::String &path) const { + return new POSIXFilesystemNode(path); + } + + /** + * Plain constructor, for internal use only (hence protected). + */ + POSIXFilesystemNode() : _isDirectory(false), _isValid(false) {} + +public: + /** + * Creates a POSIXFilesystemNode for a given path. + * + * @param path the path the new node should point to. + */ + POSIXFilesystemNode(const Common::String &path); + + virtual bool exists() const { return access(_path.c_str(), F_OK) == 0; } + virtual Common::String getDisplayName() const { return _displayName; } + virtual Common::String getName() const { return _displayName; } + virtual Common::String getPath() const { return _path; } + virtual bool isDirectory() const { return _isDirectory; } + virtual bool isReadable() const { return access(_path.c_str(), R_OK) == 0; } + virtual bool isWritable() const { return access(_path.c_str(), W_OK) == 0; } + + virtual AbstractFilesystemNode *getChild(const Common::String &n) const; + virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; + virtual AbstractFilesystemNode *getParent() const; + + virtual Common::SeekableReadStream *openForReading(); + virtual Common::WriteStream *openForWriting(); + +private: + /** + * Tests and sets the _isValid and _isDirectory flags, using the stat() function. + */ + virtual void setFlags(); +}; + +#endif /*POSIX_FILESYSTEM_H*/ diff --git a/backends/fs/ps2/ps2-fs-factory.cpp b/backends/fs/ps2/ps2-fs-factory.cpp index ce3b4a5eaf..e96671ee0a 100644 --- a/backends/fs/ps2/ps2-fs-factory.cpp +++ b/backends/fs/ps2/ps2-fs-factory.cpp @@ -36,7 +36,7 @@ AbstractFilesystemNode *Ps2FilesystemFactory::makeCurrentDirectoryFileNode() con return new Ps2FilesystemNode(); } -AbstractFilesystemNode *Ps2FilesystemFactory::makeFileNodePath(const String &path) const { +AbstractFilesystemNode *Ps2FilesystemFactory::makeFileNodePath(const Common::String &path) const { // return new Ps2FilesystemNode(path); Ps2FilesystemNode *nf = new Ps2FilesystemNode(path, true); diff --git a/backends/fs/ps2/ps2-fs-factory.h b/backends/fs/ps2/ps2-fs-factory.h index 416024c905..432cf467c3 100644 --- a/backends/fs/ps2/ps2-fs-factory.h +++ b/backends/fs/ps2/ps2-fs-factory.h @@ -35,11 +35,9 @@ */ class Ps2FilesystemFactory : public FilesystemFactory, public Common::Singleton<Ps2FilesystemFactory> { public: - typedef Common::String String; - virtual AbstractFilesystemNode *makeRootFileNode() const; virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const; - virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const; + virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const; protected: Ps2FilesystemFactory() {}; diff --git a/backends/fs/ps2/ps2-fs.cpp b/backends/fs/ps2/ps2-fs.cpp index 782e97b959..3d7656e9f0 100644 --- a/backends/fs/ps2/ps2-fs.cpp +++ b/backends/fs/ps2/ps2-fs.cpp @@ -23,6 +23,7 @@ */ #include "backends/fs/abstract-fs.h" +#include "backends/fs/stdiostream.h" #include <kernel.h> #include <stdio.h> #include <stdlib.h> @@ -47,8 +48,8 @@ class Ps2FilesystemNode : public AbstractFilesystemNode { friend class Ps2FilesystemFactory; protected: - String _displayName; - String _path; + Common::String _displayName; + Common::String _path; bool _isDirectory; bool _isRoot; @@ -65,10 +66,10 @@ public: /** * Creates a PS2FilesystemNode for a given path. * - * @param path String with the path the new node should point to. + * @param path Common::String with the path the new node should point to. */ - Ps2FilesystemNode(const String &path); - Ps2FilesystemNode(const String &path, bool verify); + Ps2FilesystemNode(const Common::String &path); + Ps2FilesystemNode(const Common::String &path, bool verify); /** * Copy constructor. @@ -77,9 +78,9 @@ public: virtual bool exists(void) const; - virtual String getDisplayName() const { return _displayName; } - virtual String getName() const { return _displayName; } - virtual String getPath() const { return _path; } + virtual Common::String getDisplayName() const { return _displayName; } + virtual Common::String getName() const { return _displayName; } + virtual Common::String getPath() const { return _path; } virtual bool isDirectory() const { return _isDirectory; @@ -95,32 +96,13 @@ public: } virtual AbstractFilesystemNode *clone() const { return new Ps2FilesystemNode(this); } - virtual AbstractFilesystemNode *getChild(const String &n) const; + virtual AbstractFilesystemNode *getChild(const Common::String &n) const; virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; virtual AbstractFilesystemNode *getParent() const; -}; - -/** - * Returns the last component of a given path. - * - * @param str String containing the path. - * @return Pointer to the first char of the last component inside str. - */ -const char *lastPathComponent(const Common::String &str) { - if (str.empty()) - return ""; - - const char *start = str.c_str(); - const char *cur = start + str.size() - 2; - - while (cur >= start && *cur != '/' && *cur != ':') { - --cur; - } - - printf("romeo : lastPathComponent = %s\n", cur + 1); - return cur + 1; -} + virtual Common::SeekableReadStream *openForReading(); + virtual Common::WriteStream *openForWriting(); +}; Ps2FilesystemNode::Ps2FilesystemNode() { _isDirectory = true; @@ -129,12 +111,12 @@ Ps2FilesystemNode::Ps2FilesystemNode() { _path = ""; } -Ps2FilesystemNode::Ps2FilesystemNode(const String &path) { +Ps2FilesystemNode::Ps2FilesystemNode(const Common::String &path) { _path = path; _isDirectory = true; if (strcmp(path.c_str(), "") == 0) { _isRoot = true; - _displayName = String("PlayStation 2"); + _displayName = Common::String("PlayStation 2"); } else { _isRoot = false; const char *dsplName = NULL, *pos = path.c_str(); @@ -142,18 +124,18 @@ Ps2FilesystemNode::Ps2FilesystemNode(const String &path) { if (*pos++ == '/') dsplName = pos; if (dsplName) - _displayName = String(dsplName); + _displayName = Common::String(dsplName); else _displayName = getDeviceDescription(path.c_str()); } } -Ps2FilesystemNode::Ps2FilesystemNode(const String &path, bool verify) { +Ps2FilesystemNode::Ps2FilesystemNode(const Common::String &path, bool verify) { _path = path; if (strcmp(path.c_str(), "") == 0) { _isRoot = true; /* root is always a dir*/ - _displayName = String("PlayStation 2"); + _displayName = Common::String("PlayStation 2"); _isDirectory = true; } else { _isRoot = false; @@ -163,7 +145,7 @@ Ps2FilesystemNode::Ps2FilesystemNode(const String &path, bool verify) { dsplName = pos; if (dsplName) { - _displayName = String(dsplName); + _displayName = Common::String(dsplName); if (verify) _isDirectory = getDirectoryFlag(path.c_str()); else @@ -228,7 +210,7 @@ bool Ps2FilesystemNode::getDirectoryFlag(const char *path) { return false; } -AbstractFilesystemNode *Ps2FilesystemNode::getChild(const String &n) const { +AbstractFilesystemNode *Ps2FilesystemNode::getChild(const Common::String &n) const { if (!_isDirectory) return NULL; @@ -306,9 +288,9 @@ bool Ps2FilesystemNode::getChildren(AbstractFSList &list, ListMode mode, bool hi while ((dreadRes = fio.dread(fd, &dirent)) > 0) { if (dirent.name[0] == '.') continue; // ignore '.' and '..' - if (((mode == FilesystemNode::kListDirectoriesOnly) && (dirent.stat.mode & FIO_S_IFDIR)) || - ((mode == FilesystemNode::kListFilesOnly) && !(dirent.stat.mode & FIO_S_IFDIR)) || - (mode == FilesystemNode::kListAll)) { + if (((mode == Common::FilesystemNode::kListDirectoriesOnly) && (dirent.stat.mode & FIO_S_IFDIR)) || + ((mode == Common::FilesystemNode::kListFilesOnly) && !(dirent.stat.mode & FIO_S_IFDIR)) || + (mode == Common::FilesystemNode::kListAll)) { dirEntry._isDirectory = (bool)(dirent.stat.mode & FIO_S_IFDIR); dirEntry._isRoot = false; @@ -344,7 +326,7 @@ AbstractFilesystemNode *Ps2FilesystemNode::getParent() const { } if (slash) - return new Ps2FilesystemNode(String(_path.c_str(), slash - _path.c_str())); + return new Ps2FilesystemNode(Common::String(_path.c_str(), slash - _path.c_str())); else return new Ps2FilesystemNode(); } @@ -359,3 +341,10 @@ char *Ps2FilesystemNode::getDeviceDescription(const char *path) const { return "Harddisk"; } +Common::SeekableReadStream *Ps2FilesystemNode::openForReading() { + return StdioStream::makeFromPath(getPath().c_str(), false); +} + +Common::WriteStream *Ps2FilesystemNode::openForWriting() { + return StdioStream::makeFromPath(getPath().c_str(), true); +} diff --git a/backends/fs/psp/psp-fs-factory.cpp b/backends/fs/psp/psp-fs-factory.cpp index 87f0e0f587..a38462f02a 100644 --- a/backends/fs/psp/psp-fs-factory.cpp +++ b/backends/fs/psp/psp-fs-factory.cpp @@ -36,7 +36,7 @@ AbstractFilesystemNode *PSPFilesystemFactory::makeCurrentDirectoryFileNode() con return new PSPFilesystemNode(); } -AbstractFilesystemNode *PSPFilesystemFactory::makeFileNodePath(const String &path) const { +AbstractFilesystemNode *PSPFilesystemFactory::makeFileNodePath(const Common::String &path) const { return new PSPFilesystemNode(path, true); } #endif diff --git a/backends/fs/psp/psp-fs-factory.h b/backends/fs/psp/psp-fs-factory.h index ffa934755f..abf03d288e 100644 --- a/backends/fs/psp/psp-fs-factory.h +++ b/backends/fs/psp/psp-fs-factory.h @@ -35,11 +35,9 @@ */ class PSPFilesystemFactory : public FilesystemFactory, public Common::Singleton<PSPFilesystemFactory> { public: - typedef Common::String String; - virtual AbstractFilesystemNode *makeRootFileNode() const; virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const; - virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const; + virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const; protected: PSPFilesystemFactory() {}; diff --git a/backends/fs/psp/psp-fs.cpp b/backends/fs/psp/psp-fs.cpp index 3fe6060928..13cd63903b 100644 --- a/backends/fs/psp/psp-fs.cpp +++ b/backends/fs/psp/psp-fs.cpp @@ -26,6 +26,7 @@ #include "engines/engine.h" #include "backends/fs/abstract-fs.h" +#include "backends/fs/stdiostream.h" #include <sys/stat.h> #include <unistd.h> @@ -39,8 +40,8 @@ */ class PSPFilesystemNode : public AbstractFilesystemNode { protected: - String _displayName; - String _path; + Common::String _displayName; + Common::String _path; bool _isDirectory; bool _isValid; @@ -53,47 +54,26 @@ public: /** * Creates a PSPFilesystemNode for a given path. * - * @param path String with the path the new node should point to. + * @param path Common::String with the path the new node should point to. * @param verify true if the isValid and isDirectory flags should be verified during the construction. */ PSPFilesystemNode(const Common::String &p, bool verify); virtual bool exists() const { return access(_path.c_str(), F_OK) == 0; } - virtual String getDisplayName() const { return _displayName; } - virtual String getName() const { return _displayName; } - virtual String getPath() const { return _path; } + virtual Common::String getDisplayName() const { return _displayName; } + virtual Common::String getName() const { return _displayName; } + virtual Common::String getPath() const { return _path; } virtual bool isDirectory() const { return _isDirectory; } virtual bool isReadable() const { return access(_path.c_str(), R_OK) == 0; } virtual bool isWritable() const { return access(_path.c_str(), W_OK) == 0; } - virtual AbstractFilesystemNode *getChild(const String &n) const; + virtual AbstractFilesystemNode *getChild(const Common::String &n) const; virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; virtual AbstractFilesystemNode *getParent() const; -}; - -/** - * Returns the last component of a given path. - * - * Examples: - * /foo/bar.txt would return /bar.txt - * /foo/bar/ would return /bar/ - * - * @param str String containing the path. - * @return Pointer to the first char of the last component inside str. - */ -const char *lastPathComponent(const Common::String &str) { - if(str.empty()) - return ""; - const char *start = str.c_str(); - const char *cur = start + str.size() - 2; - - while (cur >= start && *cur != '/') { - --cur; - } - - return cur + 1; -} + virtual Common::SeekableReadStream *openForReading(); + virtual Common::WriteStream *openForWriting(); +}; PSPFilesystemNode::PSPFilesystemNode() { _isDirectory = true; @@ -106,7 +86,7 @@ PSPFilesystemNode::PSPFilesystemNode(const Common::String &p, bool verify) { assert(p.size() > 0); _path = p; - _displayName = lastPathComponent(_path); + _displayName = lastPathComponent(_path, '/'); _isValid = true; _isDirectory = true; @@ -117,12 +97,12 @@ PSPFilesystemNode::PSPFilesystemNode(const Common::String &p, bool verify) { } } -AbstractFilesystemNode *PSPFilesystemNode::getChild(const String &n) const { +AbstractFilesystemNode *PSPFilesystemNode::getChild(const Common::String &n) const { // FIXME: Pretty lame implementation! We do no error checking to speak // of, do not check if this is a special node, etc. assert(_isDirectory); - String newPath(_path); + Common::String newPath(_path); if (_path.lastChar() != '/') newPath += '/'; newPath += n; @@ -157,8 +137,8 @@ bool PSPFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool entry._path += "/"; // Honor the chosen mode - if ((mode == FilesystemNode::kListFilesOnly && entry._isDirectory) || - (mode == FilesystemNode::kListDirectoriesOnly && !entry._isDirectory)) + if ((mode == Common::FilesystemNode::kListFilesOnly && entry._isDirectory) || + (mode == Common::FilesystemNode::kListDirectoriesOnly && !entry._isDirectory)) continue; myList.push_back(new PSPFilesystemNode(entry)); @@ -176,9 +156,17 @@ AbstractFilesystemNode *PSPFilesystemNode::getParent() const { return 0; const char *start = _path.c_str(); - const char *end = lastPathComponent(_path); + const char *end = lastPathComponent(_path, '/'); + + return new PSPFilesystemNode(Common::String(start, end - start), false); +} + +Common::SeekableReadStream *PSPFilesystemNode::openForReading() { + return StdioStream::makeFromPath(getPath().c_str(), false); +} - return new PSPFilesystemNode(String(start, end - start), false); +Common::WriteStream *PSPFilesystemNode::openForWriting() { + return StdioStream::makeFromPath(getPath().c_str(), true); } #endif //#ifdef __PSP__ diff --git a/backends/fs/stdiostream.cpp b/backends/fs/stdiostream.cpp new file mode 100644 index 0000000000..3b0de253ab --- /dev/null +++ b/backends/fs/stdiostream.cpp @@ -0,0 +1,161 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "backends/fs/stdiostream.h" + +#include <errno.h> + +#if defined(MACOSX) || defined(IPHONE) +#include "CoreFoundation/CoreFoundation.h" +#endif + + +#ifdef __PLAYSTATION2__ + // for those replaced fopen/fread/etc functions + typedef unsigned long uint64; + typedef signed long int64; + #include "backends/platform/ps2/fileio.h" + + #define fopen(a, b) ps2_fopen(a, b) + #define fclose(a) ps2_fclose(a) + #define fseek(a, b, c) ps2_fseek(a, b, c) + #define ftell(a) ps2_ftell(a) + #define feof(a) ps2_feof(a) + #define fread(a, b, c, d) ps2_fread(a, b, c, d) + #define fwrite(a, b, c, d) ps2_fwrite(a, b, c, d) + + //#define fprintf ps2_fprintf // used in common/util.cpp + //#define fflush(a) ps2_fflush(a) // used in common/util.cpp + + //#define fgetc(a) ps2_fgetc(a) // not used + //#define fgets(a, b, c) ps2_fgets(a, b, c) // not used + //#define fputc(a, b) ps2_fputc(a, b) // not used + //#define fputs(a, b) ps2_fputs(a, b) // not used + + //#define fsize(a) ps2_fsize(a) // not used -- and it is not a standard function either +#endif + +#ifdef __DS__ + + // These functions replace the standard library functions of the same name. + // As this header is included after the standard one, I have the chance to #define + // all of these to my own code. + // + // A #define is the only way, as redefinig the functions would cause linker errors. + + // These functions need to be #undef'ed, as their original definition + // in devkitarm is done with #includes (ugh!) + #undef feof + #undef clearerr + //#undef getc + //#undef ferror + + #include "backends/fs/ds/ds-fs.h" + + + // Only functions used in the ScummVM source have been defined here! + #define fopen(name, mode) DS::std_fopen(name, mode) + #define fclose(handle) DS::std_fclose(handle) + #define fread(ptr, size, items, file) DS::std_fread(ptr, size, items, file) + #define fwrite(ptr, size, items, file) DS::std_fwrite(ptr, size, items, file) + #define feof(handle) DS::std_feof(handle) + #define ftell(handle) DS::std_ftell(handle) + #define fseek(handle, offset, whence) DS::std_fseek(handle, offset, whence) + #define clearerr(handle) DS::std_clearerr(handle) + #define fflush(file) DS::std_fflush(file) + #define ferror(handle) DS::std_ferror(handle) + +#endif + +StdioStream::StdioStream(void *handle) : _handle(handle) { + assert(handle); +} + +StdioStream::~StdioStream() { + fclose((FILE *)_handle); +} + +bool StdioStream::err() const { + return ferror((FILE *)_handle) != 0; +} + +void StdioStream::clearErr() { + clearerr((FILE *)_handle); +} + +bool StdioStream::eos() const { + return feof((FILE *)_handle) != 0; +} + +int32 StdioStream::pos() const { + return ftell((FILE *)_handle); +} + +int32 StdioStream::size() const { + int32 oldPos = ftell((FILE *)_handle); + fseek((FILE *)_handle, 0, SEEK_END); + int32 length = ftell((FILE *)_handle); + fseek((FILE *)_handle, oldPos, SEEK_SET); + + return length; +} + +bool StdioStream::seek(int32 offs, int whence) { + return fseek((FILE *)_handle, offs, whence) == 0; +} + +uint32 StdioStream::read(void *ptr, uint32 len) { + return fread((byte *)ptr, 1, len, (FILE *)_handle); +} + +uint32 StdioStream::write(const void *ptr, uint32 len) { + return fwrite(ptr, 1, len, (FILE *)_handle); +} + +bool StdioStream::flush() { + return fflush((FILE *)_handle) == 0; +} + +StdioStream *StdioStream::makeFromPath(const Common::String &path, bool writeMode) { + FILE *handle = fopen(path.c_str(), writeMode ? "wb" : "rb"); + +#ifdef __amigaos4__ + // + // Work around for possibility that someone uses AmigaOS "newlib" build + // with SmartFileSystem (blocksize 512 bytes), leading to buffer size + // being only 512 bytes. "Clib2" sets the buffer size to 8KB, resulting + // smooth movie playback. This forces the buffer to be enough also when + // using "newlib" compile on SFS. + // + if (handle && !writeMode) { + setvbuf(handle, NULL, _IOFBF, 8192); + } +#endif + + + if (handle) + return new StdioStream(handle); + return 0; +} diff --git a/backends/fs/stdiostream.h b/backends/fs/stdiostream.h new file mode 100644 index 0000000000..3d44062d7f --- /dev/null +++ b/backends/fs/stdiostream.h @@ -0,0 +1,62 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_FS_STDIOSTREAM_H +#define BACKENDS_FS_STDIOSTREAM_H + +#include "common/scummsys.h" +#include "common/noncopyable.h" +#include "common/stream.h" +#include "common/str.h" + +class StdioStream : public Common::SeekableReadStream, public Common::WriteStream, public Common::NonCopyable { +protected: + /** File handle to the actual file. */ + void *_handle; + +public: + /** + * Given a path, invokes fopen on that path and wrap the result in a + * StdioStream instance. + */ + static StdioStream *makeFromPath(const Common::String &path, bool writeMode); + + StdioStream(void *handle); + virtual ~StdioStream(); + + bool err() const; + void clearErr(); + bool eos() const; + + virtual uint32 write(const void *dataPtr, uint32 dataSize); + virtual bool flush(); + + virtual int32 pos() const; + virtual int32 size() const; + bool seek(int32 offs, int whence = SEEK_SET); + uint32 read(void *dataPtr, uint32 dataSize); +}; + +#endif diff --git a/backends/fs/symbian/symbian-fs-factory.cpp b/backends/fs/symbian/symbian-fs-factory.cpp index 0a1bd62134..c31dfb594a 100644 --- a/backends/fs/symbian/symbian-fs-factory.cpp +++ b/backends/fs/symbian/symbian-fs-factory.cpp @@ -26,8 +26,6 @@ #include "backends/fs/symbian/symbian-fs-factory.h" #include "backends/fs/symbian/symbian-fs.cpp" -DECLARE_SINGLETON(SymbianFilesystemFactory); - AbstractFilesystemNode *SymbianFilesystemFactory::makeRootFileNode() const { return new SymbianFilesystemNode(true); } @@ -38,7 +36,7 @@ AbstractFilesystemNode *SymbianFilesystemFactory::makeCurrentDirectoryFileNode() return new SymbianFilesystemNode(path); } -AbstractFilesystemNode *SymbianFilesystemFactory::makeFileNodePath(const String &path) const { +AbstractFilesystemNode *SymbianFilesystemFactory::makeFileNodePath(const Common::String &path) const { return new SymbianFilesystemNode(path); } #endif diff --git a/backends/fs/symbian/symbian-fs-factory.h b/backends/fs/symbian/symbian-fs-factory.h index 502fba2930..ef5a231e72 100644 --- a/backends/fs/symbian/symbian-fs-factory.h +++ b/backends/fs/symbian/symbian-fs-factory.h @@ -25,7 +25,6 @@ #ifndef SYMBIAN_FILESYSTEM_FACTORY_H #define SYMBIAN_FILESYSTEM_FACTORY_H -#include "common/singleton.h" #include "backends/fs/fs-factory.h" /** @@ -33,19 +32,11 @@ * * Parts of this class are documented in the base interface class, FilesystemFactory. */ -class SymbianFilesystemFactory : public FilesystemFactory, public Common::Singleton<SymbianFilesystemFactory> { +class SymbianFilesystemFactory : public FilesystemFactory { public: - typedef Common::String String; - virtual AbstractFilesystemNode *makeRootFileNode() const; virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const; - virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const; - -protected: - SymbianFilesystemFactory() {}; - -private: - friend class Common::Singleton<SingletonBaseType>; + virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const; }; #endif /*SYMBIAN_FILESYSTEM_FACTORY_H*/ diff --git a/backends/fs/symbian/symbian-fs.cpp b/backends/fs/symbian/symbian-fs.cpp index 85fc58179a..1c6d8435a9 100644 --- a/backends/fs/symbian/symbian-fs.cpp +++ b/backends/fs/symbian/symbian-fs.cpp @@ -24,12 +24,16 @@ #if defined (__SYMBIAN32__) #include "backends/fs/abstract-fs.h" +#include "backends/fs/symbian/symbianstream.h" +#include "backends/platform/symbian/src/symbianos.h" #include <dirent.h> #include <eikenv.h> #include <f32file.h> #include <bautils.h> +#define KDriveLabelSize 30 + /** * Implementation of the ScummVM file system API based on POSIX. * @@ -37,12 +41,11 @@ */ class SymbianFilesystemNode : public AbstractFilesystemNode { protected: - String _displayName; - String _path; - bool _isDirectory; - bool _isValid; - bool _isPseudoRoot; - + Common::String _displayName; + Common::String _path; + TBool _isDirectory; + TBool _isValid; + TBool _isPseudoRoot; public: /** * Creates a SymbianFilesystemNode with the root node as path. @@ -54,57 +57,36 @@ public: /** * Creates a SymbianFilesystemNode for a given path. * - * @param path String with the path the new node should point to. + * @param path Common::String with the path the new node should point to. */ - SymbianFilesystemNode(const String &path); + SymbianFilesystemNode(const Common::String &path); virtual bool exists() const { TFileName fname; - TPtrC8 ptr((const unsigned char*)_path.c_str(),_path.size()); + TPtrC8 ptr((const unsigned char*) _path.c_str(), _path.size()); fname.Copy(ptr); - TBool fileExists = BaflUtils::FileExists(CEikonEnv::Static()->FsSession(), fname); + TBool fileExists = BaflUtils::FileExists(static_cast<OSystem_SDL_Symbian*> (g_system)->FsSession(), fname); return fileExists; } - virtual String getDisplayName() const { return _displayName; } - virtual String getName() const { return _displayName; } - virtual String getPath() const { return _path; } + virtual Common::String getDisplayName() const { return _displayName; } + virtual Common::String getName() const { return _displayName; } + virtual Common::String getPath() const { return _path; } virtual bool isDirectory() const { return _isDirectory; } virtual bool isReadable() const { return access(_path.c_str(), R_OK) == 0; } //FIXME: this is just a stub virtual bool isWritable() const { return access(_path.c_str(), W_OK) == 0; } //FIXME: this is just a stub - virtual AbstractFilesystemNode *getChild(const String &n) const; + virtual AbstractFilesystemNode *getChild(const Common::String &n) const; virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; virtual AbstractFilesystemNode *getParent() const; -}; -/** - * Returns the last component of a given path. - * - * Examples: - * c:\foo\bar.txt would return "\bar.txt" - * c:\foo\bar\ would return "\bar\" - * - * @param str Path to obtain the last component from. - * @return Pointer to the first char of the last component inside str. - */ -const char *lastPathComponent(const Common::String &str) { - if(str.empty()) - return ""; - - const char *start = str.c_str(); - const char *cur = start + str.size() - 2; - - while (cur >= start && *cur != '\\') { - --cur; - } - - return cur + 1; -} + virtual Common::SeekableReadStream *openForReading(); + virtual Common::WriteStream *openForWriting(); +}; /** * Fixes the path by changing all slashes to backslashes. * - * @param path String with the path to be fixed. + * @param path Common::String with the path to be fixed. */ static void fixFilePath(Common::String& aPath){ TInt len = aPath.size(); @@ -118,54 +100,47 @@ static void fixFilePath(Common::String& aPath){ SymbianFilesystemNode::SymbianFilesystemNode(bool aIsRoot) { _path = ""; - _isValid = true; - _isDirectory = true; + _isValid = ETrue; + _isDirectory = ETrue; _isPseudoRoot = aIsRoot; _displayName = "Root"; } -SymbianFilesystemNode::SymbianFilesystemNode(const String &path) { +SymbianFilesystemNode::SymbianFilesystemNode(const Common::String &path) { if (path.size() == 0) - _isPseudoRoot = true; + _isPseudoRoot = ETrue; else - _isPseudoRoot = false; + _isPseudoRoot = EFalse; _path = path; fixFilePath(_path); - _displayName = lastPathComponent(_path); + _displayName = lastPathComponent(_path, '\\'); TEntry fileAttribs; TFileName fname; TPtrC8 ptr((const unsigned char*)_path.c_str(),_path.size()); fname.Copy(ptr); - if (CEikonEnv::Static()->FsSession().Entry(fname, fileAttribs) == KErrNone) { - _isValid = true; + if (static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession().Entry(fname, fileAttribs) == KErrNone) { + _isValid = ETrue; _isDirectory = fileAttribs.IsDir(); } else { - _isValid = false; - _isDirectory = false; + _isValid = ETrue; + _isDirectory = EFalse; } } -AbstractFilesystemNode *SymbianFilesystemNode::getChild(const String &n) const { +AbstractFilesystemNode *SymbianFilesystemNode::getChild(const Common::String &n) const { assert(_isDirectory); - String newPath(_path); + Common::String newPath(_path); if (_path.lastChar() != '\\') newPath += '\\'; - newPath += n; - TPtrC8 ptr((const unsigned char*) newPath.c_str(), newPath.size()); - TFileName fname; - fname.Copy(ptr); - TBool isFolder = EFalse; - BaflUtils::IsFolder(CEikonEnv::Static()->FsSession(), fname, isFolder); - if (!isFolder) - return 0; + newPath += n; return new SymbianFilesystemNode(newPath); } @@ -177,19 +152,19 @@ bool SymbianFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, b if (_isPseudoRoot) { // Drives enumeration - RFs fs = CEikonEnv::Static()->FsSession(); + RFs& fs = static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession(); TInt driveNumber; TChar driveLetter; TUint driveLetterValue; TVolumeInfo volumeInfo; - TBuf8<30> driveLabel8; - TBuf8<30> driveString8; + TBuf8<KDriveLabelSize> driveLabel8; + TBuf8<KDriveLabelSize> driveString8; for (driveNumber=EDriveA; driveNumber<=EDriveZ; driveNumber++) { TInt err = fs.Volume(volumeInfo, driveNumber); if (err != KErrNone) continue; - if (fs.DriveToChar(driveNumber,driveLetter) != KErrNone) + if (fs.DriveToChar(driveNumber, driveLetter) != KErrNone) continue; driveLetterValue = driveLetter; @@ -205,40 +180,46 @@ bool SymbianFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, b sprintf(path,"%c:\\", driveNumber+'A'); SymbianFilesystemNode entry(false); - entry._displayName = (char*)driveString8.PtrZ(); // drive_name - entry._isDirectory = true; - entry._isValid = true; - entry._isPseudoRoot = false; + entry._displayName = (char*) driveString8.PtrZ(); // drive_name + entry._isDirectory = ETrue; + entry._isValid = ETrue; + entry._isPseudoRoot = EFalse; entry._path = path; myList.push_back(new SymbianFilesystemNode(entry)); } } else { - TPtrC8 ptr((const unsigned char*)_path.c_str(),_path.size()); + TPtrC8 ptr((const unsigned char*) _path.c_str(), _path.size()); TFileName fname; - fname.Copy(ptr); TBuf8<256>nameBuf; CDir* dirPtr; - if (CEikonEnv::Static()->FsSession().GetDir(fname,KEntryAttNormal|KEntryAttDir,0,dirPtr)==KErrNone) { + fname.Copy(ptr); + + if (_path.lastChar() != '\\') + fname.Append('\\'); + + if (static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession().GetDir(fname, KEntryAttNormal|KEntryAttDir, 0, dirPtr) == KErrNone) { CleanupStack::PushL(dirPtr); TInt cnt=dirPtr->Count(); for (TInt loop=0;loop<cnt;loop++) { TEntry fileentry=(*dirPtr)[loop]; nameBuf.Copy(fileentry.iName); - SymbianFilesystemNode entry(false); - entry._isPseudoRoot = false; + SymbianFilesystemNode entry(EFalse); + entry._isPseudoRoot = EFalse; - entry._displayName =(char*)nameBuf.PtrZ(); + entry._displayName =(char*) nameBuf.PtrZ(); entry._path = _path; - entry._path +=(char*)nameBuf.PtrZ(); + + if (entry._path.lastChar() != '\\') + entry._path+= '\\'; + + entry._path +=(char*) nameBuf.PtrZ(); entry._isDirectory = fileentry.IsDir(); // Honor the chosen mode - if ((mode == FilesystemNode::kListFilesOnly && entry._isDirectory) || - (mode == FilesystemNode::kListDirectoriesOnly && !entry._isDirectory)) + if ((mode == Common::FilesystemNode::kListFilesOnly && entry._isDirectory) || + (mode == Common::FilesystemNode::kListDirectoriesOnly && !entry._isDirectory)) continue; - - if (entry._isDirectory) - entry._path += "\\"; + myList.push_back(new SymbianFilesystemNode(entry)); } CleanupStack::PopAndDestroy(dirPtr); @@ -254,21 +235,30 @@ AbstractFilesystemNode *SymbianFilesystemNode::getParent() const { // Root node is its own parent. Still we can't just return this // as the GUI code will call delete on the old node. if (!_isPseudoRoot && _path.size() > 3) { - p = new SymbianFilesystemNode(false); + p = new SymbianFilesystemNode(EFalse); const char *start = _path.c_str(); - const char *end = lastPathComponent(_path); + const char *end = lastPathComponent(_path, '\\'); - p->_path = String(start, end - start); - p->_isValid = true; - p->_isDirectory = true; - p->_displayName = lastPathComponent(p->_path); + p->_path = Common::String(start, end - start); + p->_isValid = ETrue; + p->_isDirectory = ETrue; + p->_displayName = lastPathComponent(p->_path, '\\'); } else { - p = new SymbianFilesystemNode(true); + p = new SymbianFilesystemNode(ETrue); } return p; } +Common::SeekableReadStream *SymbianFilesystemNode::openForReading() { + return SymbianStdioStream::makeFromPath(getPath().c_str(), false); +} + +Common::WriteStream *SymbianFilesystemNode::openForWriting() { + return SymbianStdioStream::makeFromPath(getPath().c_str(), true); +} #endif //#if defined (__SYMBIAN32__) + + diff --git a/backends/fs/symbian/symbianstream.cpp b/backends/fs/symbian/symbianstream.cpp new file mode 100644 index 0000000000..5944cab892 --- /dev/null +++ b/backends/fs/symbian/symbianstream.cpp @@ -0,0 +1,274 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/scummsys.h" +#include "backends/fs/symbian/symbianstream.h" +#include "common/system.h" +#include "backends/platform/symbian/src/symbianos.h" + +#include <f32file.h> + +#define KInputBufferLength 128 + +// Symbian libc file functionality in order to provide shared file handles +class TSymbianFileEntry { +public: + RFile _fileHandle; + char _inputBuffer[KInputBufferLength]; + TInt _inputBufferLen; + TInt _inputPos; + TInt _lastError; + TBool _eofReached; +}; + +TSymbianFileEntry* CreateSymbianFileEntry(const char* name, const char* mode) { + TSymbianFileEntry* fileEntry = new TSymbianFileEntry; + fileEntry->_inputPos = KErrNotFound; + fileEntry->_lastError = 0; + fileEntry->_eofReached = EFalse; + + if (fileEntry != NULL) { + TInt modeLen = strlen(mode); + + TPtrC8 namePtr((unsigned char*) name, strlen(name)); + TFileName tempFileName; + tempFileName.Copy(namePtr); + + TInt fileMode = EFileRead; + + if (mode[0] == 'a') + fileMode = EFileWrite; + + if (!((modeLen > 1 && mode[1] == 'b') || (modeLen > 2 && mode[2] == 'b'))) { + fileMode |= EFileStreamText; + } + + if ((modeLen > 1 && mode[1] == '+') || (modeLen > 2 && mode[2] == '+')) { + fileMode = fileMode| EFileWrite; + } + + fileMode = fileMode| EFileShareAny; + + switch(mode[0]) { + case 'a': + if (fileEntry->_fileHandle.Open(static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession(), tempFileName, fileMode) != KErrNone) { + if (fileEntry->_fileHandle.Create(static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession(), tempFileName, fileMode) != KErrNone) { + delete fileEntry; + fileEntry = NULL; + } + } + break; + case 'r': + if (fileEntry->_fileHandle.Open(static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession(), tempFileName, fileMode) != KErrNone) { + delete fileEntry; + fileEntry = NULL; + } + break; + + case 'w': + if (fileEntry->_fileHandle.Replace(static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession(), tempFileName, fileMode) != KErrNone) { + delete fileEntry; + fileEntry = NULL; + } + break; + } + } + return fileEntry; +} + +size_t ReadData(const void* ptr, size_t size, size_t numItems, TSymbianFileEntry* handle) { + TSymbianFileEntry* entry = ((TSymbianFileEntry*)(handle)); + TUint32 totsize = size*numItems; + TPtr8 pointer ( (unsigned char*) ptr, totsize); + + // Nothing cached and we want to load at least KInputBufferLength bytes + if (totsize >= KInputBufferLength) { + TUint32 totLength = 0; + if (entry->_inputPos != KErrNotFound) { + TPtr8 cacheBuffer( (unsigned char*) entry->_inputBuffer+entry->_inputPos, entry->_inputBufferLen - entry->_inputPos, KInputBufferLength); + pointer.Append(cacheBuffer); + entry->_inputPos = KErrNotFound; + totLength+=pointer.Length(); + pointer.Set(totLength+(unsigned char*) ptr, 0, totsize-totLength); + } + + entry->_lastError = entry->_fileHandle.Read(pointer); + + totLength+=pointer.Length(); + + pointer.Set((unsigned char*) ptr, totLength, totsize); + + } else { + // Nothing in buffer + if (entry->_inputPos == KErrNotFound) { + TPtr8 cacheBuffer( (unsigned char*) entry->_inputBuffer, KInputBufferLength); + entry->_lastError = entry->_fileHandle.Read(cacheBuffer); + + if (cacheBuffer.Length() >= totsize) { + pointer.Copy(cacheBuffer.Left(totsize)); + entry->_inputPos = totsize; + entry->_inputBufferLen = cacheBuffer.Length(); + } else { + pointer.Copy(cacheBuffer); + entry->_inputPos = KErrNotFound; + } + + } else { + TPtr8 cacheBuffer( (unsigned char*) entry->_inputBuffer, entry->_inputBufferLen, KInputBufferLength); + + if (entry->_inputPos+totsize < entry->_inputBufferLen) { + pointer.Copy(cacheBuffer.Mid(entry->_inputPos, totsize)); + entry->_inputPos+=totsize; + } else { + + pointer.Copy(cacheBuffer.Mid(entry->_inputPos, entry->_inputBufferLen-entry->_inputPos)); + cacheBuffer.SetLength(0); + entry->_lastError = entry->_fileHandle.Read(cacheBuffer); + + if (cacheBuffer.Length() >= totsize-pointer.Length()) { + TUint32 restSize = totsize-pointer.Length(); + pointer.Append(cacheBuffer.Left(restSize)); + entry->_inputPos = restSize; + entry->_inputBufferLen = cacheBuffer.Length(); + } else { + pointer.Append(cacheBuffer); + entry->_inputPos = KErrNotFound; + } + } + } + } + + if((numItems * size) != pointer.Length() && entry->_lastError == KErrNone) { + entry->_eofReached = ETrue; + } + + return pointer.Length() / size; +} + +SymbianStdioStream::SymbianStdioStream(void *handle) : _handle(handle) { + assert(handle); +} + +SymbianStdioStream::~SymbianStdioStream() { + ((TSymbianFileEntry*)(_handle))->_fileHandle.Close(); + + delete (TSymbianFileEntry*)(_handle); +} + +bool SymbianStdioStream::err() const { + return ((TSymbianFileEntry*)(_handle))->_lastError != 0; +} + +void SymbianStdioStream::clearErr() { + ((TSymbianFileEntry*)(_handle))->_lastError = 0; + ((TSymbianFileEntry*)(_handle))->_eofReached = 0; +} + +bool SymbianStdioStream::eos() const { + TSymbianFileEntry* entry = ((TSymbianFileEntry*)(_handle)); + + return entry->_eofReached != 0; +} + +int32 SymbianStdioStream::pos() const { + TInt pos = 0; + TSymbianFileEntry* entry = ((TSymbianFileEntry*)(_handle)); + + entry->_lastError = entry->_fileHandle.Seek(ESeekCurrent, pos); + if (entry->_lastError == KErrNone && entry->_inputPos != KErrNotFound) { + pos += (entry->_inputPos - entry->_inputBufferLen); + } + + return pos; +} + +int32 SymbianStdioStream::size() const { + + TInt length = 0; + ((TSymbianFileEntry*)(_handle))->_fileHandle.Size(length); + + return length; +} + +bool SymbianStdioStream::seek(int32 offs, int whence) { + assert(_handle); + + TSeek seekMode = ESeekStart; + TInt pos = offs; + TSymbianFileEntry* entry = ((TSymbianFileEntry*)(_handle)); + + switch (whence) { + case SEEK_SET: + seekMode = ESeekStart; + break; + case SEEK_CUR: + seekMode = ESeekCurrent; + if (entry->_inputPos != KErrNotFound) { + pos += (entry->_inputPos - entry->_inputBufferLen); + } + break; + case SEEK_END: + seekMode = ESeekEnd; + break; + + } + + entry->_inputPos = KErrNotFound; + entry->_eofReached = EFalse; + entry->_fileHandle.Seek(seekMode, pos); + + return true; // FIXME: Probably should return a value based on what _fileHandle.Seek returns +} + +uint32 SymbianStdioStream::read(void *ptr, uint32 len) { + return (uint32)ReadData((byte *)ptr, 1, len, (TSymbianFileEntry *)_handle); +} + +uint32 SymbianStdioStream::write(const void *ptr, uint32 len) { + TPtrC8 pointer( (unsigned char*) ptr, len); + + ((TSymbianFileEntry*)(_handle))->_inputPos = KErrNotFound; + ((TSymbianFileEntry*)(_handle))->_lastError = ((TSymbianFileEntry*)(_handle))->_fileHandle.Write(pointer); + ((TSymbianFileEntry*)(_handle))->_eofReached = EFalse; + + if (((TSymbianFileEntry*)(_handle))->_lastError == KErrNone) { + return len; + } + + return 0; +} + +bool SymbianStdioStream::flush() { + ((TSymbianFileEntry*)(_handle))->_fileHandle.Flush(); + return true; +} + +SymbianStdioStream *SymbianStdioStream::makeFromPath(const Common::String &path, bool writeMode) { + void *handle = CreateSymbianFileEntry(path.c_str(), writeMode ? "wb" : "rb"); + if (handle) + return new SymbianStdioStream(handle); + return 0; +} + diff --git a/backends/fs/symbian/symbianstream.h b/backends/fs/symbian/symbianstream.h new file mode 100644 index 0000000000..d783856687 --- /dev/null +++ b/backends/fs/symbian/symbianstream.h @@ -0,0 +1,62 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL: $ + * $Id: $ + * + */ + +#ifndef BACKENDS_FS_SYMBIANSTDIOSTREAM_H +#define BACKENDS_FS_SYMBIANSTDIOSTREAM_H + +#include "common/scummsys.h" +#include "common/noncopyable.h" +#include "common/stream.h" +#include "common/str.h" + +class SymbianStdioStream : public Common::SeekableReadStream, public Common::WriteStream, public Common::NonCopyable { +protected: + /** File handle to the actual file. */ + void *_handle; + +public: + /** + * Given a path, invokes fopen on that path and wrap the result in a + * StdioStream instance. + */ + static SymbianStdioStream *makeFromPath(const Common::String &path, bool writeMode); + + SymbianStdioStream(void *handle); + virtual ~SymbianStdioStream(); + + bool err() const; + void clearErr(); + bool eos() const; + + virtual uint32 write(const void *dataPtr, uint32 dataSize); + virtual bool flush(); + + virtual int32 pos() const; + virtual int32 size() const; + bool seek(int32 offs, int whence = SEEK_SET); + uint32 read(void *dataPtr, uint32 dataSize); +}; + +#endif diff --git a/backends/fs/wii/wii-fs-factory.cpp b/backends/fs/wii/wii-fs-factory.cpp index 9839858dd5..69086a95f1 100644 --- a/backends/fs/wii/wii-fs-factory.cpp +++ b/backends/fs/wii/wii-fs-factory.cpp @@ -42,7 +42,7 @@ AbstractFilesystemNode *WiiFilesystemFactory::makeCurrentDirectoryFileNode() con return new WiiFilesystemNode(); } -AbstractFilesystemNode *WiiFilesystemFactory::makeFileNodePath(const String &path) const { +AbstractFilesystemNode *WiiFilesystemFactory::makeFileNodePath(const Common::String &path) const { return new WiiFilesystemNode(path, true); } #endif diff --git a/backends/fs/wii/wii-fs-factory.h b/backends/fs/wii/wii-fs-factory.h index 24badee330..36867a392c 100644 --- a/backends/fs/wii/wii-fs-factory.h +++ b/backends/fs/wii/wii-fs-factory.h @@ -33,11 +33,9 @@ */ class WiiFilesystemFactory : public FilesystemFactory, public Common::Singleton<WiiFilesystemFactory> { public: - typedef Common::String String; - virtual AbstractFilesystemNode *makeRootFileNode() const; virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const; - virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const; + virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const; protected: WiiFilesystemFactory() {}; diff --git a/backends/fs/wii/wii-fs.cpp b/backends/fs/wii/wii-fs.cpp index e6d0cf4c7e..a620df5471 100644 --- a/backends/fs/wii/wii-fs.cpp +++ b/backends/fs/wii/wii-fs.cpp @@ -23,6 +23,7 @@ #if defined(__WII__) #include "backends/fs/abstract-fs.h" +#include "backends/fs/stdiostream.h" #include <sys/dir.h> @@ -37,8 +38,8 @@ */ class WiiFilesystemNode : public AbstractFilesystemNode { protected: - String _displayName; - String _path; + Common::String _displayName; + Common::String _path; bool _isDirectory, _isReadable, _isWritable; public: @@ -50,51 +51,30 @@ public: /** * Creates a WiiFilesystemNode for a given path. * - * @param path String with the path the new node should point to. + * @param path Common::String with the path the new node should point to. * @param verify true if the isValid and isDirectory flags should be verified during the construction. */ - WiiFilesystemNode(const String &path, bool verify); + WiiFilesystemNode(const Common::String &path, bool verify); virtual bool exists() const; - virtual String getDisplayName() const { return _displayName; } - virtual String getName() const { return _displayName; } - virtual String getPath() const { return _path; } + virtual Common::String getDisplayName() const { return _displayName; } + virtual Common::String getName() const { return _displayName; } + virtual Common::String getPath() const { return _path; } virtual bool isDirectory() const { return _isDirectory; } virtual bool isReadable() const { return _isReadable; } virtual bool isWritable() const { return _isWritable; } - virtual AbstractFilesystemNode *getChild(const String &n) const; + virtual AbstractFilesystemNode *getChild(const Common::String &n) const; virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; virtual AbstractFilesystemNode *getParent() const; + virtual Common::SeekableReadStream *openForReading(); + virtual Common::WriteStream *openForWriting(); + private: virtual void setFlags(); }; -/** - * Returns the last component of a given path. - * - * Examples: - * /foo/bar.txt would return /bar.txt - * /foo/bar/ would return /bar/ - * - * @param str String containing the path. - * @return Pointer to the first char of the last component inside str. - */ -const char *lastPathComponent(const Common::String &str) { - if(str.empty()) - return ""; - - const char *start = str.c_str(); - const char *cur = start + str.size() - 2; - - while (cur >= start && *cur != '/') { - --cur; - } - - return cur + 1; -} - void WiiFilesystemNode::setFlags() { struct stat st; @@ -118,12 +98,12 @@ WiiFilesystemNode::WiiFilesystemNode() { setFlags(); } -WiiFilesystemNode::WiiFilesystemNode(const String &p, bool verify) { +WiiFilesystemNode::WiiFilesystemNode(const Common::String &p, bool verify) { assert(p.size() > 0); _path = p; - _displayName = lastPathComponent(_path); + _displayName = lastPathComponent(_path, '/'); if (verify) setFlags(); @@ -134,10 +114,10 @@ bool WiiFilesystemNode::exists() const { return stat(_path.c_str (), &st) == 0; } -AbstractFilesystemNode *WiiFilesystemNode::getChild(const String &n) const { +AbstractFilesystemNode *WiiFilesystemNode::getChild(const Common::String &n) const { assert(_isDirectory); - String newPath(_path); + Common::String newPath(_path); if (newPath.lastChar() != '/') newPath += '/'; newPath += n; @@ -160,15 +140,15 @@ bool WiiFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0) continue; - String newPath(_path); + Common::String newPath(_path); if (newPath.lastChar() != '/') newPath += '/'; newPath += filename; bool isDir = S_ISDIR(st.st_mode); - if ((mode == FilesystemNode::kListFilesOnly && isDir) || - (mode == FilesystemNode::kListDirectoriesOnly && !isDir)) + if ((mode == Common::FilesystemNode::kListFilesOnly && isDir) || + (mode == Common::FilesystemNode::kListDirectoriesOnly && !isDir)) continue; if (isDir) @@ -187,9 +167,17 @@ AbstractFilesystemNode *WiiFilesystemNode::getParent() const { return 0; const char *start = _path.c_str(); - const char *end = lastPathComponent(_path); + const char *end = lastPathComponent(_path, '/'); + + return new WiiFilesystemNode(Common::String(start, end - start), true); +} + +Common::SeekableReadStream *WiiFilesystemNode::openForReading() { + return StdioStream::makeFromPath(getPath().c_str(), false); +} - return new WiiFilesystemNode(String(start, end - start), true); +Common::WriteStream *WiiFilesystemNode::openForWriting() { + return StdioStream::makeFromPath(getPath().c_str(), true); } #endif //#if defined(__WII__) diff --git a/backends/fs/windows/windows-fs-factory.cpp b/backends/fs/windows/windows-fs-factory.cpp index 7fbf4f7fff..ed273bb746 100644 --- a/backends/fs/windows/windows-fs-factory.cpp +++ b/backends/fs/windows/windows-fs-factory.cpp @@ -26,8 +26,6 @@ #include "backends/fs/windows/windows-fs-factory.h" #include "backends/fs/windows/windows-fs.cpp" -DECLARE_SINGLETON(WindowsFilesystemFactory); - AbstractFilesystemNode *WindowsFilesystemFactory::makeRootFileNode() const { return new WindowsFilesystemNode(); } @@ -36,7 +34,7 @@ AbstractFilesystemNode *WindowsFilesystemFactory::makeCurrentDirectoryFileNode() return new WindowsFilesystemNode("", true); } -AbstractFilesystemNode *WindowsFilesystemFactory::makeFileNodePath(const String &path) const { +AbstractFilesystemNode *WindowsFilesystemFactory::makeFileNodePath(const Common::String &path) const { return new WindowsFilesystemNode(path, false); } #endif diff --git a/backends/fs/windows/windows-fs-factory.h b/backends/fs/windows/windows-fs-factory.h index 0745b286a8..3c7b80942d 100644 --- a/backends/fs/windows/windows-fs-factory.h +++ b/backends/fs/windows/windows-fs-factory.h @@ -25,7 +25,6 @@ #ifndef WINDOWS_FILESYSTEM_FACTORY_H #define WINDOWS_FILESYSTEM_FACTORY_H -#include "common/singleton.h" #include "backends/fs/fs-factory.h" /** @@ -33,19 +32,11 @@ * * Parts of this class are documented in the base interface class, FilesystemFactory. */ -class WindowsFilesystemFactory : public FilesystemFactory, public Common::Singleton<WindowsFilesystemFactory> { +class WindowsFilesystemFactory : public FilesystemFactory { public: - typedef Common::String String; - virtual AbstractFilesystemNode *makeRootFileNode() const; virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const; - virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const; - -protected: - WindowsFilesystemFactory() {}; - -private: - friend class Common::Singleton<SingletonBaseType>; + virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const; }; #endif /*WINDOWS_FILESYSTEM_FACTORY_H*/ diff --git a/backends/fs/windows/windows-fs.cpp b/backends/fs/windows/windows-fs.cpp index ac2f521e21..c59c7dbe71 100644 --- a/backends/fs/windows/windows-fs.cpp +++ b/backends/fs/windows/windows-fs.cpp @@ -24,24 +24,17 @@ #ifdef WIN32 -#ifdef ARRAYSIZE -#undef ARRAYSIZE -#endif -#ifdef _WIN32_WCE #include <windows.h> // winnt.h defines ARRAYSIZE, but we want our own one... #undef ARRAYSIZE +#ifdef _WIN32_WCE #undef GetCurrentDirectory #endif #include "backends/fs/abstract-fs.h" +#include "backends/fs/stdiostream.h" #include <io.h> #include <stdio.h> #include <stdlib.h> -#ifndef _WIN32_WCE -#include <windows.h> -// winnt.h defines ARRAYSIZE, but we want our own one... -#undef ARRAYSIZE -#endif #include <tchar.h> // F_OK, R_OK and W_OK are not defined under MSVC, so we define them here @@ -66,8 +59,8 @@ */ class WindowsFilesystemNode : public AbstractFilesystemNode { protected: - String _displayName; - String _path; + Common::String _displayName; + Common::String _path; bool _isDirectory; bool _isPseudoRoot; bool _isValid; @@ -89,23 +82,26 @@ public: * path=c:\foo\bar.txt, currentDir=true -> current directory * path=NULL, currentDir=true -> current directory * - * @param path String with the path the new node should point to. + * @param path Common::String with the path the new node should point to. * @param currentDir if true, the path parameter will be ignored and the resulting node will point to the current directory. */ - WindowsFilesystemNode(const String &path, const bool currentDir); + WindowsFilesystemNode(const Common::String &path, const bool currentDir); virtual bool exists() const { return _access(_path.c_str(), F_OK) == 0; } - virtual String getDisplayName() const { return _displayName; } - virtual String getName() const { return _displayName; } - virtual String getPath() const { return _path; } + virtual Common::String getDisplayName() const { return _displayName; } + virtual Common::String getName() const { return _displayName; } + virtual Common::String getPath() const { return _path; } virtual bool isDirectory() const { return _isDirectory; } virtual bool isReadable() const { return _access(_path.c_str(), R_OK) == 0; } virtual bool isWritable() const { return _access(_path.c_str(), W_OK) == 0; } - virtual AbstractFilesystemNode *getChild(const String &n) const; + virtual AbstractFilesystemNode *getChild(const Common::String &n) const; virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; virtual AbstractFilesystemNode *getParent() const; + virtual Common::SeekableReadStream *openForReading(); + virtual Common::WriteStream *openForWriting(); + private: /** * Adds a single WindowsFilesystemNode to a given list. @@ -113,7 +109,7 @@ private: * * @param list List to put the file entry node in. * @param mode Mode to use while adding the file entry to the list. - * @param base String with the directory being listed. + * @param base Common::String with the directory being listed. * @param find_data Describes a file that the FindFirstFile, FindFirstFileEx, or FindNextFile functions find. */ static void addFile(AbstractFSList &list, ListMode mode, const char *base, WIN32_FIND_DATA* find_data); @@ -121,7 +117,7 @@ private: /** * Converts a Unicode string to Ascii format. * - * @param str String to convert from Unicode to Ascii. + * @param str Common::String to convert from Unicode to Ascii. * @return str in Ascii format. */ static char *toAscii(TCHAR *str); @@ -129,36 +125,12 @@ private: /** * Converts an Ascii string to Unicode format. * - * @param str String to convert from Ascii to Unicode. + * @param str Common::String to convert from Ascii to Unicode. * @return str in Unicode format. */ static const TCHAR* toUnicode(const char *str); }; -/** - * Returns the last component of a given path. - * - * Examples: - * c:\foo\bar.txt would return "\bar.txt" - * c:\foo\bar\ would return "\bar\" - * - * @param str Path to obtain the last component from. - * @return Pointer to the first char of the last component inside str. - */ -const char *lastPathComponent(const Common::String &str) { - if(str.empty()) - return ""; - - const char *start = str.c_str(); - const char *cur = start + str.size() - 2; - - while (cur >= start && *cur != '\\') { - --cur; - } - - return cur + 1; -} - void WindowsFilesystemNode::addFile(AbstractFSList &list, ListMode mode, const char *base, WIN32_FIND_DATA* find_data) { WindowsFilesystemNode entry; char *asciiName = toAscii(find_data->cFileName); @@ -170,8 +142,8 @@ void WindowsFilesystemNode::addFile(AbstractFSList &list, ListMode mode, const c isDirectory = (find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? true : false); - if ((!isDirectory && mode == FilesystemNode::kListDirectoriesOnly) || - (isDirectory && mode == FilesystemNode::kListFilesOnly)) + if ((!isDirectory && mode == Common::FilesystemNode::kListDirectoriesOnly) || + (isDirectory && mode == Common::FilesystemNode::kListFilesOnly)) return; entry._isDirectory = isDirectory; @@ -222,18 +194,17 @@ WindowsFilesystemNode::WindowsFilesystemNode() { #endif } -WindowsFilesystemNode::WindowsFilesystemNode(const String &p, const bool currentDir) { +WindowsFilesystemNode::WindowsFilesystemNode(const Common::String &p, const bool currentDir) { if (currentDir) { char path[MAX_PATH]; GetCurrentDirectory(MAX_PATH, path); _path = path; - } - else { + } else { assert(p.size() > 0); _path = p; } - _displayName = lastPathComponent(_path); + _displayName = lastPathComponent(_path, '\\'); // Check whether it is a directory, and whether the file actually exists DWORD fileAttribs = GetFileAttributes(toUnicode(_path.c_str())); @@ -252,19 +223,14 @@ WindowsFilesystemNode::WindowsFilesystemNode(const String &p, const bool current _isPseudoRoot = false; } -AbstractFilesystemNode *WindowsFilesystemNode::getChild(const String &n) const { +AbstractFilesystemNode *WindowsFilesystemNode::getChild(const Common::String &n) const { assert(_isDirectory); - String newPath(_path); + Common::String newPath(_path); if (_path.lastChar() != '\\') newPath += '\\'; newPath += n; - // Check whether the directory actually exists - DWORD fileAttribs = GetFileAttributes(toUnicode(newPath.c_str())); - if (fileAttribs == INVALID_FILE_ATTRIBUTES) - return 0; - return new WindowsFilesystemNode(newPath, false); } @@ -328,17 +294,25 @@ AbstractFilesystemNode *WindowsFilesystemNode::getParent() const { WindowsFilesystemNode *p = new WindowsFilesystemNode(); if (_path.size() > 3) { const char *start = _path.c_str(); - const char *end = lastPathComponent(_path); + const char *end = lastPathComponent(_path, '\\'); p = new WindowsFilesystemNode(); - p->_path = String(start, end - start); + p->_path = Common::String(start, end - start); p->_isValid = true; p->_isDirectory = true; - p->_displayName = lastPathComponent(p->_path); + p->_displayName = lastPathComponent(p->_path, '\\'); p->_isPseudoRoot = false; } return p; } +Common::SeekableReadStream *WindowsFilesystemNode::openForReading() { + return StdioStream::makeFromPath(getPath().c_str(), false); +} + +Common::WriteStream *WindowsFilesystemNode::openForWriting() { + return StdioStream::makeFromPath(getPath().c_str(), true); +} + #endif //#ifdef WIN32 |