[Scummvm-cvs-logs] SF.net SVN: scummvm:[33121] residual/trunk/common
aquadran at users.sourceforge.net
aquadran at users.sourceforge.net
Sun Jul 20 15:18:27 CEST 2008
Revision: 33121
http://scummvm.svn.sourceforge.net/scummvm/?rev=33121&view=rev
Author: aquadran
Date: 2008-07-20 13:16:56 +0000 (Sun, 20 Jul 2008)
Log Message:
-----------
added filesystem common code from scummvm (part 1)
Modified Paths:
--------------
residual/trunk/common/module.mk
residual/trunk/common/sys.h
residual/trunk/common/util.h
Added Paths:
-----------
residual/trunk/common/error.h
residual/trunk/common/file.cpp
residual/trunk/common/file.h
residual/trunk/common/fs.cpp
residual/trunk/common/fs.h
residual/trunk/common/ptr.h
residual/trunk/common/savefile.h
residual/trunk/common/singleton.h
residual/trunk/common/stream.cpp
residual/trunk/common/stream.h
Added: residual/trunk/common/error.h
===================================================================
--- residual/trunk/common/error.h (rev 0)
+++ residual/trunk/common/error.h 2008-07-20 13:16:56 UTC (rev 33121)
@@ -0,0 +1,47 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ *
+ * Residual is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the AUTHORS
+ * 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 COMMON_ERROR_H
+#define COMMON_ERROR_H
+
+/**
+ * This file contains enums with error codes commonly used.
+ */
+
+/**
+ * Errors used in the SaveFileManager class.
+ */
+enum SFMError {
+ SFM_NO_ERROR, //Default state, indicates no error has been recorded
+ SFM_DIR_ACCESS, //stat(), mkdir()::EACCES: Search or write permission denied
+ SFM_DIR_LINKMAX, //mkdir()::EMLINK: The link count of the parent directory would exceed {LINK_MAX}
+ SFM_DIR_LOOP, //stat(), mkdir()::ELOOP: Too many symbolic links encountered while traversing the path
+ SFM_DIR_NAMETOOLONG, //stat(), mkdir()::ENAMETOOLONG: The path name is too long
+ SFM_DIR_NOENT, //stat(), mkdir()::ENOENT: A component of the path path does not exist, or the path is an empty string
+ SFM_DIR_NOTDIR, //stat(), mkdir()::ENOTDIR: A component of the path prefix is not a directory
+ SFM_DIR_ROFS //mkdir()::EROFS: The parent directory resides on a read-only file system
+};
+
+#endif //COMMON_ERROR_H
Property changes on: residual/trunk/common/error.h
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Revision Author URL Id
Added: svn:eol-style
+ native
Added: residual/trunk/common/file.cpp
===================================================================
--- residual/trunk/common/file.cpp (rev 0)
+++ residual/trunk/common/file.cpp 2008-07-20 13:16:56 UTC (rev 33121)
@@ -0,0 +1,542 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ *
+ * Residual is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the AUTHORS
+ * 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/file.h"
+#include "common/fs.h"
+#include "common/hashmap.h"
+#include "common/util.h"
+#include "common/debug.h"
+#include "common/hash-str.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 replease 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"
+
+
+ //void std_fprintf(FILE* handle, const char* fmt, ...); // used in common/util.cpp
+ //void std_fflush(FILE* handle); // used in common/util.cpp
+
+ //char* std_fgets(char* str, int size, FILE* file); // not used
+ //int std_getc(FILE* handle); // not used
+ //char* std_getcwd(char* dir, int dunno); // not used
+ //void std_cwd(char* dir); // not used
+ //int std_ferror(FILE* handle); // not used
+
+ // 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 printf(fmt, ...) consolePrintf(fmt, ##__VA_ARGS__)
+
+ //#define fprintf(file, fmt, ...) { char str[128]; sprintf(str, fmt, ##__VA_ARGS__); DS::std_fwrite(str, strlen(str), 1, file); }
+ //#define fflush(file) DS::std_fflush(file) // used in common/util.cpp
+
+ //#define fgets(str, size, file) DS::std_fgets(str, size, file) // not used
+ //#define getc(handle) DS::std_getc(handle) // not used
+ //#define getcwd(dir, dunno) DS::std_getcwd(dir, dunno) // not used
+ //#define ferror(handle) DS::std_ferror(handle) // not used
+
+#endif
+
+#ifdef __SYMBIAN32__
+ #undef feof
+ #undef clearerr
+
+ #define FILE void
+
+ FILE* symbian_fopen(const char* name, const char* mode);
+ void symbian_fclose(FILE* handle);
+ size_t symbian_fread(const void* ptr, size_t size, size_t numItems, FILE* handle);
+ size_t symbian_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle);
+ bool symbian_feof(FILE* handle);
+ long int symbian_ftell(FILE* handle);
+ int symbian_fseek(FILE* handle, long int offset, int whence);
+ void symbian_clearerr(FILE* handle);
+
+ // Only functions used in the ScummVM source have been defined here!
+ #define fopen(name, mode) symbian_fopen(name, mode)
+ #define fclose(handle) symbian_fclose(handle)
+ #define fread(ptr, size, items, file) symbian_fread(ptr, size, items, file)
+ #define fwrite(ptr, size, items, file) symbian_fwrite(ptr, size, items, file)
+ #define feof(handle) symbian_feof(handle)
+ #define ftell(handle) symbian_ftell(handle)
+ #define fseek(handle, offset, whence) symbian_fseek(handle, offset, whence)
+ #define clearerr(handle) symbian_clearerr(handle)
+#endif
+
+namespace Common {
+
+typedef HashMap<String, int> StringIntMap;
+
+// The following two objects could be turned into static members of class
+// File. However, then we would be forced to #include hashmap in file.h
+// which seems to be a high price just for a simple beautification...
+static StringIntMap *_defaultDirectories;
+static StringMap *_filesMap;
+
+static FILE *fopenNoCase(const String &filename, const String &directory, const char *mode) {
+ FILE *file;
+ String dirBuf(directory);
+ String fileBuf(filename);
+
+#if !defined(__GP32__) && !defined(PALMOS_MODE)
+ // Add a trailing slash, if necessary.
+ if (!dirBuf.empty()) {
+ const char c = dirBuf.lastChar();
+ if (c != ':' && c != '/' && c != '\\')
+ dirBuf += '/';
+ }
+#endif
+
+ // Append the filename to the path string
+ String pathBuf(dirBuf);
+ pathBuf += fileBuf;
+
+ //
+ // Try to open the file normally
+ //
+ file = fopen(pathBuf.c_str(), mode);
+
+ //
+ // Try again, with file name converted to upper case
+ //
+ if (!file) {
+ fileBuf.toUppercase();
+ pathBuf = dirBuf + fileBuf;
+ file = fopen(pathBuf.c_str(), mode);
+ }
+
+ //
+ // Try again, with file name converted to lower case
+ //
+ if (!file) {
+ fileBuf.toLowercase();
+ pathBuf = dirBuf + fileBuf;
+ file = fopen(pathBuf.c_str(), mode);
+ }
+
+ //
+ // Try again, with file name capitalized
+ //
+ if (!file) {
+ fileBuf.toLowercase();
+ fileBuf.setChar(toupper(fileBuf[0]),0);
+ pathBuf = dirBuf + fileBuf;
+ file = fopen(pathBuf.c_str(), mode);
+ }
+
+#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 (file) {
+ setvbuf(file, NULL, _IOFBF, 8192);
+ }
+#endif
+
+ return file;
+}
+
+void File::addDefaultDirectory(const String &directory) {
+ FilesystemNode dir(directory);
+ addDefaultDirectoryRecursive(dir, 1);
+}
+
+void File::addDefaultDirectoryRecursive(const String &directory, int level, const String &prefix) {
+ FilesystemNode dir(directory);
+ addDefaultDirectoryRecursive(dir, level, prefix);
+}
+
+void File::addDefaultDirectory(const FilesystemNode &directory) {
+ addDefaultDirectoryRecursive(directory, 1);
+}
+
+void File::addDefaultDirectoryRecursive(const FilesystemNode &dir, int level, const String &prefix) {
+ if (level <= 0)
+ return;
+
+ FSList fslist;
+ if (!dir.getChildren(fslist, FilesystemNode::kListAll)) {
+ // Failed listing the contents of this node, so it is either not a
+ // directory, or just doesn't exist at all.
+ return;
+ }
+
+ if (!_defaultDirectories)
+ _defaultDirectories = new StringIntMap;
+
+ // Do not add directories multiple times, unless this time they are added
+ // with a bigger depth.
+ const String &directory(dir.getPath());
+ if (_defaultDirectories->contains(directory) && (*_defaultDirectories)[directory] >= level)
+ return;
+ (*_defaultDirectories)[directory] = level;
+
+ if (!_filesMap)
+ _filesMap = new StringMap;
+
+ for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
+ if (file->isDirectory()) {
+ addDefaultDirectoryRecursive(file->getPath(), level - 1, prefix + file->getName() + "/");
+ } else {
+ String lfn(prefix);
+ lfn += file->getName();
+ lfn.toLowercase();
+ if (!_filesMap->contains(lfn)) {
+ (*_filesMap)[lfn] = file->getPath();
+ }
+ }
+ }
+}
+
+void File::resetDefaultDirectories() {
+ delete _defaultDirectories;
+ delete _filesMap;
+
+ _defaultDirectories = 0;
+ _filesMap = 0;
+}
+
+File::File()
+ : _handle(0), _ioFailed(false) {
+}
+
+//#define DEBUG_FILE_REFCOUNT
+
+File::~File() {
+#ifdef DEBUG_FILE_REFCOUNT
+ warning("File::~File on file '%s'", _name.c_str());
+#endif
+ close();
+}
+
+
+bool File::open(const String &filename, AccessMode mode) {
+ assert(mode == kFileReadMode || mode == kFileWriteMode);
+
+ if (filename.empty()) {
+ error("File::open: No filename was specified");
+ }
+
+ if (_handle) {
+ error("File::open: This file object already is opened (%s), won't open '%s'", _name.c_str(), filename.c_str());
+ }
+
+ _name.clear();
+ clearIOFailed();
+
+ String fname(filename);
+ fname.toLowercase();
+
+ const char *modeStr = (mode == kFileReadMode) ? "rb" : "wb";
+ if (mode == kFileWriteMode) {
+ _handle = fopenNoCase(filename, "", modeStr);
+ } else if (_filesMap && _filesMap->contains(fname)) {
+ fname = (*_filesMap)[fname];
+ //debug(3, "Opening hashed: %s", fname.c_str());
+ _handle = fopen(fname.c_str(), modeStr);
+ } else if (_filesMap && _filesMap->contains(fname + ".")) {
+ // WORKAROUND: Bug #1458388: "SIMON1: Game Detection fails"
+ // sometimes instead of "GAMEPC" we get "GAMEPC." (note trailing dot)
+ fname = (*_filesMap)[fname + "."];
+ //debug(3, "Opening hashed: %s", fname.c_str());
+ _handle = fopen(fname.c_str(), modeStr);
+ } else {
+
+ if (_defaultDirectories) {
+ // Try all default directories
+ StringIntMap::const_iterator x(_defaultDirectories->begin());
+ for (; _handle == NULL && x != _defaultDirectories->end(); ++x) {
+ _handle = fopenNoCase(filename, x->_key, modeStr);
+ }
+ }
+
+ // Last resort: try the current directory
+ if (_handle == NULL)
+ _handle = fopenNoCase(filename, "", modeStr);
+
+ // Last last (really) resort: try looking inside the application bundle on Mac OS X for the lowercase file.
+#if defined(MACOSX) || defined(IPHONE)
+ if (!_handle) {
+ CFStringRef cfFileName = CFStringCreateWithBytes(NULL, (const UInt8 *)filename.c_str(), filename.size(), kCFStringEncodingASCII, false);
+ CFURLRef fileUrl = CFBundleCopyResourceURL(CFBundleGetMainBundle(), cfFileName, NULL, NULL);
+ if (fileUrl) {
+ UInt8 buf[256];
+ if (CFURLGetFileSystemRepresentation(fileUrl, false, (UInt8 *)buf, 256)) {
+ _handle = fopen((char *)buf, modeStr);
+ }
+ CFRelease(fileUrl);
+ }
+ CFRelease(cfFileName);
+ }
+#endif
+
+ }
+
+ if (_handle == NULL) {
+/* if (mode == kFileReadMode)
+ debug(2, "File %s not found", filename.c_str());
+ else
+ debug(2, "File %s not opened", filename.c_str());*/
+ return false;
+ }
+
+
+ _name = filename;
+
+#ifdef DEBUG_FILE_REFCOUNT
+ warning("File::open on file '%s'", _name.c_str());
+#endif
+
+ return true;
+}
+
+bool File::open(const FilesystemNode &node, AccessMode mode) {
+ assert(mode == kFileReadMode || mode == kFileWriteMode);
+
+ if (!node.exists()) {
+ warning("File::open: Trying to open a FilesystemNode which does not exist");
+ return false;
+ } else if (node.isDirectory()) {
+ warning("File::open: Trying to open a FilesystemNode which is a directory");
+ return false;
+ } /*else if (!node.isReadable() && mode == kFileReadMode) {
+ warning("File::open: Trying to open an unreadable FilesystemNode object for reading");
+ return false;
+ } else if (!node.isWritable() && mode == kFileWriteMode) {
+ warning("File::open: Trying to open an unwritable FilesystemNode object for writing");
+ return false;
+ }*/
+
+ String filename(node.getName());
+
+ if (_handle) {
+ error("File::open: This file object already is opened (%s), won't open '%s'", _name.c_str(), filename.c_str());
+ }
+
+ clearIOFailed();
+ _name.clear();
+
+ const char *modeStr = (mode == kFileReadMode) ? "rb" : "wb";
+
+ _handle = fopen(node.getPath().c_str(), modeStr);
+
+ if (_handle == NULL) {
+/* if (mode == kFileReadMode)
+ debug(2, "File %s not found", filename.c_str());
+ else
+ debug(2, "File %s not opened", filename.c_str());*/
+ return false;
+ }
+
+ _name = filename;
+
+#ifdef DEBUG_FILE_REFCOUNT
+ warning("File::open on file '%s'", _name.c_str());
+#endif
+
+ return true;
+}
+
+bool File::exists(const String &filename) {
+ // First try to find the file via a FilesystemNode (in case an absolute
+ // path was passed). This is only used to filter out directories.
+ FilesystemNode file(filename);
+ if (file.exists())
+ return !file.isDirectory();
+
+ // See if the file is already mapped
+ if (_filesMap && _filesMap->contains(filename)) {
+ FilesystemNode file2((*_filesMap)[filename]);
+
+ if (file2.exists())
+ return !file2.isDirectory();
+ }
+
+ // Try all default directories
+ if (_defaultDirectories) {
+ StringIntMap::const_iterator i(_defaultDirectories->begin());
+ for (; i != _defaultDirectories->end(); ++i) {
+ FilesystemNode file2(i->_key + filename);
+
+ if(file2.exists())
+ return !file2.isDirectory();
+ }
+ }
+
+ //Try opening the file inside the local directory as a last resort
+ File tmp;
+ return tmp.open(filename, kFileReadMode);
+}
+
+void File::close() {
+ if (_handle)
+ fclose((FILE *)_handle);
+ _handle = NULL;
+}
+
+bool File::isOpen() const {
+ return _handle != NULL;
+}
+
+bool File::ioFailed() const {
+ return _ioFailed != 0;
+}
+
+void File::clearIOFailed() {
+ _ioFailed = false;
+}
+
+bool File::eof() const {
+ if (_handle == NULL) {
+ error("File::eof: File is not open!");
+ return false;
+ }
+
+ return feof((FILE *)_handle) != 0;
+}
+
+uint32 File::pos() const {
+ if (_handle == NULL) {
+ error("File::pos: File is not open!");
+ return 0;
+ }
+
+ return ftell((FILE *)_handle);
+}
+
+uint32 File::size() const {
+ if (_handle == NULL) {
+ error("File::size: File is not open!");
+ return 0;
+ }
+
+ uint32 oldPos = ftell((FILE *)_handle);
+ fseek((FILE *)_handle, 0, SEEK_END);
+ uint32 length = ftell((FILE *)_handle);
+ fseek((FILE *)_handle, oldPos, SEEK_SET);
+
+ return length;
+}
+
+void File::seek(int32 offs, int whence) {
+ if (_handle == NULL) {
+ error("File::seek: File is not open!");
+ return;
+ }
+
+ if (fseek((FILE *)_handle, offs, whence) != 0)
+ clearerr((FILE *)_handle);
+}
+
+uint32 File::read(void *ptr, uint32 len) {
+ byte *ptr2 = (byte *)ptr;
+ uint32 real_len;
+
+ if (_handle == NULL) {
+ error("File::read: File is not open!");
+ return 0;
+ }
+
+ if (len == 0)
+ return 0;
+
+ real_len = fread(ptr2, 1, len, (FILE *)_handle);
+ if (real_len < len) {
+ _ioFailed = true;
+ }
+
+ return real_len;
+}
+
+uint32 File::write(const void *ptr, uint32 len) {
+ if (_handle == NULL) {
+ error("File::write: File is not open!");
+ return 0;
+ }
+
+ if (len == 0)
+ return 0;
+
+ if ((uint32)fwrite(ptr, 1, len, (FILE *)_handle) != len) {
+ _ioFailed = true;
+ }
+
+ return len;
+}
+
+} // End of namespace Common
Property changes on: residual/trunk/common/file.cpp
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Revision Author URL Id
Added: svn:eol-style
+ native
Added: residual/trunk/common/file.h
===================================================================
--- residual/trunk/common/file.h (rev 0)
+++ residual/trunk/common/file.h 2008-07-20 13:16:56 UTC (rev 33121)
@@ -0,0 +1,122 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ *
+ * Residual is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the AUTHORS
+ * 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 COMMON_FILE_H
+#define COMMON_FILE_H
+
+#include "common/sys.h"
+#include "common/str.h"
+#include "common/stream.h"
+
+class FilesystemNode;
+
+namespace Common {
+
+class File : public SeekableReadStream, public WriteStream {
+protected:
+ /** File handle to the actual file; 0 if no file is open. */
+ void *_handle;
+
+ /** Status flag which tells about recent I/O failures. */
+ bool _ioFailed;
+
+ /** The name of this file, for debugging. */
+ String _name;
+
+private:
+ // Disallow copying File objects. There is not strict reason for this,
+ // except that so far we never had real need for such a feature, and
+ // code that accidentally copied File objects tended to break in strange
+ // ways.
+ File(const File &f);
+ File &operator =(const File &f);
+
+public:
+ enum AccessMode {
+ kFileReadMode = 1,
+ kFileWriteMode = 2
+ };
+
+ static void addDefaultDirectory(const String &directory);
+ static void addDefaultDirectoryRecursive(const String &directory, int level = 4, const String &prefix = "");
+
+ static void addDefaultDirectory(const FilesystemNode &directory);
+ static void addDefaultDirectoryRecursive(const FilesystemNode &directory, int level = 4, const String &prefix = "");
+
+ static void resetDefaultDirectories();
+
+ File();
+ virtual ~File();
+
+ /**
+ * Checks if a given file exists in any of the current default paths
+ * (those were/are added by addDefaultDirectory and/or
+ * addDefaultDirectoryRecursive).
+ *
+ * @param filename: the file to check for
+ * @return: true if the file exists, else false
+ */
+ static bool exists(const String &filename);
+
+ virtual bool open(const String &filename, AccessMode mode = kFileReadMode);
+ virtual bool open(const FilesystemNode &node, AccessMode mode = kFileReadMode);
+
+ virtual void close();
+
+ /**
+ * Checks if the object opened a file successfully.
+ *
+ * @return: true if any file is opened, false otherwise.
+ */
+ bool isOpen() const;
+
+ /**
+ * Returns the filename of the opened file.
+ *
+ * @return: the filename
+ */
+ const char *name() const { return _name.c_str(); }
+
+ bool ioFailed() const;
+ void clearIOFailed();
+ bool eos() const { return eof(); }
+
+ /**
+ * Checks for end of file.
+ *
+ * @return: true if the end of file is reached, false otherwise.
+ */
+ virtual bool eof() const;
+
+ virtual uint32 pos() const;
+ virtual uint32 size() const;
+ void seek(int32 offs, int whence = SEEK_SET);
+ uint32 read(void *dataPtr, uint32 dataSize);
+ uint32 write(const void *dataPtr, uint32 dataSize);
+};
+
+} // End of namespace Common
+
+#endif
Property changes on: residual/trunk/common/file.h
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Revision Author URL Id
Added: svn:eol-style
+ native
Added: residual/trunk/common/fs.cpp
===================================================================
--- residual/trunk/common/fs.cpp (rev 0)
+++ residual/trunk/common/fs.cpp 2008-07-20 13:16:56 UTC (rev 33121)
@@ -0,0 +1,205 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ *
+ * Residual is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the AUTHORS
+ * 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/util.h"
+#include "engine/backend/driver.h"
+#include "engine/backend/fs/abstract-fs.h"
+#include "engine/backend/fs/fs-factory.h"
+
+static bool matchString(const char *str, const char *pat) {
+ const char *p = 0;
+ const char *q = 0;
+
+ for (;;) {
+ switch (*pat) {
+ case '*':
+ p = ++pat;
+ q = str;
+ break;
+
+ default:
+ if (*pat != *str) {
+ if (p) {
+ pat = p;
+ str = ++q;
+ if (!*str)
+ return !*pat;
+ break;
+ }
+ else
+ return false;
+ }
+ // fallthrough
+ case '?':
+ if (!*str)
+ return !*pat;
+ pat++;
+ str++;
+ }
+ }
+}
+
+FilesystemNode::FilesystemNode() {
+}
+
+FilesystemNode::FilesystemNode(AbstractFilesystemNode *realNode)
+ : _realNode(realNode) {
+}
+
+FilesystemNode::FilesystemNode(const Common::String &p) {
+ FilesystemFactory *factory = g_driver->getFilesystemFactory();
+ AbstractFilesystemNode *tmp = 0;
+
+ if (p.empty() || p == ".")
+ tmp = factory->makeCurrentDirectoryFileNode();
+ else
+ tmp = factory->makeFileNodePath(p);
+ _realNode = Common::SharedPtr<AbstractFilesystemNode>(tmp);
+}
+
+bool FilesystemNode::operator<(const FilesystemNode& node) const {
+ if (isDirectory() != node.isDirectory())
+ return isDirectory();
+
+ return strcasecmp(getDisplayName().c_str(), node.getDisplayName().c_str()) < 0;
+}
+
+bool FilesystemNode::exists() const {
+ if (_realNode == 0)
+ return false;
+
+ return _realNode->exists();
+}
+
+FilesystemNode FilesystemNode::getChild(const Common::String &n) const {
+ if (_realNode == 0)
+ return *this;
+
+ assert(_realNode->isDirectory());
+ AbstractFilesystemNode *node = _realNode->getChild(n);
+ return FilesystemNode(node);
+}
+
+bool FilesystemNode::getChildren(FSList &fslist, ListMode mode, bool hidden) const {
+ if (!_realNode || !_realNode->isDirectory())
+ return false;
+
+ AbstractFSList tmp;
+
+ if (!_realNode->getChildren(tmp, mode, hidden))
+ return false;
+
+ fslist.clear();
+ for (AbstractFSList::iterator i = tmp.begin(); i != tmp.end(); ++i) {
+ fslist.push_back(FilesystemNode(*i));
+ }
+
+ return true;
+}
+
+Common::String FilesystemNode::getDisplayName() const {
+ assert(_realNode);
+ return _realNode->getDisplayName();
+}
+
+Common::String FilesystemNode::getName() const {
+ assert(_realNode);
+ return _realNode->getName();
+}
+
+FilesystemNode FilesystemNode::getParent() const {
+ if (_realNode == 0)
+ return *this;
+
+ AbstractFilesystemNode *node = _realNode->getParent();
+ if (node == 0) {
+ return *this;
+ } else {
+ return FilesystemNode(node);
+ }
+}
+
+Common::String FilesystemNode::getPath() const {
+ assert(_realNode);
+ return _realNode->getPath();
+}
+
+bool FilesystemNode::isDirectory() const {
+ if (_realNode == 0)
+ return false;
+
+ return _realNode->isDirectory();
+}
+
+bool FilesystemNode::isReadable() const {
+ if (_realNode == 0)
+ return false;
+
+ return _realNode->isReadable();
+}
+
+bool FilesystemNode::isWritable() const {
+ if (_realNode == 0)
+ return false;
+
+ return _realNode->isWritable();
+}
+
+bool FilesystemNode::lookupFile(FSList &results, const Common::String &p, bool hidden, bool exhaustive, int depth) const {
+ if (!isDirectory())
+ return false;
+
+ FSList children;
+ FSList subdirs;
+ Common::String pattern = p;
+
+ pattern.toUppercase();
+
+ // First match all files on this level
+ getChildren(children, FilesystemNode::kListAll, hidden);
+ for (FSList::iterator entry = children.begin(); entry != children.end(); ++entry) {
+ if (entry->isDirectory()) {
+ if (depth != 0)
+ subdirs.push_back(*entry);
+ } else {
+ Common::String filename = entry->getName();
+ filename.toUppercase();
+ if (matchString(filename.c_str(), pattern.c_str())) {
+ results.push_back(*entry);
+
+ if (!exhaustive)
+ return true; // Abort on first match if no exhaustive search was requested
+ }
+ }
+ }
+
+ // Now scan all subdirs
+ for (FSList::iterator child = subdirs.begin(); child != subdirs.end(); ++child) {
+ child->lookupFile(results, pattern, hidden, exhaustive, depth - 1);
+ if (!exhaustive && !results.empty())
+ return true; // Abort on first match if no exhaustive search was requested
+ }
+
+ return !results.empty();
+}
Property changes on: residual/trunk/common/fs.cpp
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Revision Author URL Id
Added: svn:eol-style
+ native
Added: residual/trunk/common/fs.h
===================================================================
--- residual/trunk/common/fs.h (rev 0)
+++ residual/trunk/common/fs.h 2008-07-20 13:16:56 UTC (rev 33121)
@@ -0,0 +1,228 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ *
+ * Residual is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the AUTHORS
+ * 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 COMMON_FS_H
+#define COMMON_FS_H
+
+#include "common/array.h"
+#include "common/ptr.h"
+#include "common/str.h"
+
+//namespace Common {
+
+class FilesystemNode;
+class AbstractFilesystemNode;
+
+/**
+ * List of multiple file system nodes. E.g. the contents of a given directory.
+ * This is subclass instead of just a typedef so that we can use forward
+ * declarations of it in other places.
+ */
+class FSList : public Common::Array<FilesystemNode> {};
+
+/**
+ * FilesystemNode provides an abstraction for file paths, allowing for portable
+ * file system browsing. To this ends, multiple or single roots have to be supported
+ * (compare Unix with a single root, Windows with multiple roots C:, D:, ...).
+ *
+ * To this end, we abstract away from paths; implementations can be based on
+ * paths (and it's left to them whether / or \ or : is the path separator :-);
+ * but it is also possible to use inodes or vrefs (MacOS 9) or anything else.
+ *
+ * NOTE: Backends still have to provide a way to extract a path from a FSIntern
+ *
+ * You may ask now: "isn't this cheating? Why do we go through all this when we use
+ * a path in the end anyway?!?".
+ * Well, for once as long as we don't provide our own file open/read/write API, we
+ * still have to use fopen(). Since all our targets already support fopen(), it should
+ * be possible to get a fopen() compatible string for any file system node.
+ *
+ * Secondly, with this abstraction layer, we still avoid a lot of complications based on
+ * differences in FS roots, different path separators, or even systems with no real
+ * paths (MacOS 9 doesn't even have the notion of a "current directory").
+ * And if we ever want to support devices with no FS in the classical sense (Palm...),
+ * we can build upon this.
+ *
+ * This class acts as a wrapper around the AbstractFilesystemNode class defined in backends/fs.
+ */
+class FilesystemNode {
+private:
+ Common::SharedPtr<AbstractFilesystemNode> _realNode;
+ FilesystemNode(AbstractFilesystemNode *realNode);
+
+public:
+ /**
+ * Flag to tell listDir() which kind of files to list.
+ */
+ enum ListMode {
+ kListFilesOnly = 1,
+ kListDirectoriesOnly = 2,
+ kListAll = 3
+ };
+
+ /**
+ * Create a new pathless FilesystemNode. Since there's no path associated
+ * with this node, path-related operations (i.e. exists(), isDirectory(),
+ * getPath()) will always return false or raise an assertion.
+ */
+ FilesystemNode();
+
+ /**
+ * Create a new FilesystemNode referring to the specified path. This is
+ * the counterpart to the path() method.
+ *
+ * If path is empty or equals ".", then a node representing the "current
+ * directory" will be created. If that is not possible (since e.g. the
+ * operating system doesn't support the concept), some other directory is
+ * used (usually the root directory).
+ */
+ explicit FilesystemNode(const Common::String &path);
+
+ virtual ~FilesystemNode() {}
+
+ /**
+ * Compare the name of this node to the name of another. Directories
+ * go before normal files.
+ */
+ bool operator<(const FilesystemNode& node) const;
+
+ /**
+ * Indicates whether the object referred by this path exists in the filesystem or not.
+ *
+ * @return bool true if the path exists, false otherwise.
+ */
+ virtual bool exists() const;
+
+ /**
+ * Fetch a child node of this node, with the given name. Only valid for
+ * directory nodes (an assertion is triggered otherwise).
+ * If no child node with the given name exists, an invalid node is returned.
+ */
+ FilesystemNode getChild(const Common::String &name) const;
+
+ /**
+ * Return a list of child nodes of this directory node. If called on a node
+ * that does not represent a directory, false is returned.
+ *
+ * @return true if succesful, false otherwise (e.g. when the directory does not exist).
+ */
+ virtual bool getChildren(FSList &fslist, ListMode mode = kListDirectoriesOnly, bool hidden = false) const;
+
+ /**
+ * Return a human readable string for this node, usable for display (e.g.
+ * in the GUI code). Do *not* rely on it being usable for anything else,
+ * like constructing paths!
+ *
+ * @return the display name
+ */
+ virtual Common::String getDisplayName() const;
+
+ /**
+ * Return a string representation of the name of the file. This is can be
+ * used e.g. by detection code that relies on matching the name of a given
+ * file. But it is *not* suitable for use with fopen / File::open, nor
+ * should it be archived.
+ *
+ * @return the file name
+ */
+ virtual Common::String getName() const;
+
+ /**
+ * Return a string representation of the file which can be passed to fopen(),
+ * and is suitable for archiving (i.e. writing to the config file).
+ * This will usually be a 'path' (hence the name of the method), but can
+ * be anything that fulfills the above criterions.
+ *
+ * @note Do not assume that this string contains (back)slashes or any
+ * other kind of 'path separators'.
+ *
+ * @return the 'path' represented by this filesystem node
+ */
+ virtual Common::String getPath() const;
+
+ /**
+ * Get the parent node of this node. If this node has no parent node,
+ * then it returns a duplicate of this node.
+ */
+ FilesystemNode getParent() const;
+
+ /**
+ * Indicates whether the path refers to a directory or not.
+ *
+ * @todo Currently we assume that a node that is not a directory
+ * automatically is a file (ignoring things like symlinks or pipes).
+ * That might actually be OK... but we could still add an isFile method.
+ * Or even replace isDirectory by a getType() method that can return values like
+ * kDirNodeType, kFileNodeType, kInvalidNodeType.
+ */
+ virtual bool isDirectory() const;
+
+ /**
+ * Indicates whether the object referred by this path can be read from or not.
+ *
+ * If the path refers to a directory, readability implies being able to read
+ * and list the directory entries.
+ *
+ * If the path refers to a file, readability implies being able to read the
+ * contents of the file.
+ *
+ * @return bool true if the object can be read, false otherwise.
+ */
+ virtual bool isReadable() const;
+
+ /**
+ * Indicates whether the object referred by this path can be written to or not.
+ *
+ * If the path refers to a directory, writability implies being able to modify
+ * the directory entry (i.e. rename the directory, remove it or write files inside of it).
+ *
+ * If the path refers to a file, writability implies being able to write data
+ * to the file.
+ *
+ * @return bool true if the object can be written to, false otherwise.
+ */
+ virtual bool isWritable() const;
+
+ /**
+ * Searches recursively for files matching the specified pattern inside this directory and
+ * all its subdirectories. It is safe to call this method for non-directories, in this case
+ * it will just return false.
+ *
+ * The files in each directory are scanned first. Other than that, a depth first search
+ * is performed.
+ *
+ * @param results List to put the matches in.
+ * @param pattern Pattern of the files to look for.
+ * @param hidden Whether to search hidden files or not.
+ * @param exhaustive Whether to continue searching after one match has been found.
+ * @param depth How many levels to search through (-1 = search all subdirs, 0 = only the current one)
+ *
+ * @return true if matches could be found, false otherwise.
+ */
+ virtual bool lookupFile(FSList &results, const Common::String &pattern, bool hidden, bool exhaustive, int depth = -1) const;
+};
+
+//} // End of namespace Common
+
+#endif //COMMON_FS_H
Property changes on: residual/trunk/common/fs.h
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Revision Author URL Id
Added: svn:eol-style
+ native
Modified: residual/trunk/common/module.mk
===================================================================
--- residual/trunk/common/module.mk 2008-07-20 11:15:29 UTC (rev 33120)
+++ residual/trunk/common/module.mk 2008-07-20 13:16:56 UTC (rev 33121)
@@ -2,11 +2,14 @@
MODULE_OBJS := \
debug.o \
+ file.o \
+ fs.o \
hashmap.o \
matrix3.o \
matrix4.o \
memorypool.o \
str.o \
+ stream.o \
mutex.o
# Include common rules
Added: residual/trunk/common/ptr.h
===================================================================
--- residual/trunk/common/ptr.h (rev 0)
+++ residual/trunk/common/ptr.h 2008-07-20 13:16:56 UTC (rev 33121)
@@ -0,0 +1,215 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ *
+ * Residual is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the AUTHORS
+ * 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 COMMON_PTR_H
+#define COMMON_PTR_H
+
+#include "common/sys.h"
+
+namespace Common {
+
+class SharedPtrDeletionInternal {
+public:
+ virtual ~SharedPtrDeletionInternal() {}
+};
+
+template<class T>
+class SharedPtrDeletionImpl : public SharedPtrDeletionInternal {
+public:
+ SharedPtrDeletionImpl(T *ptr) : _ptr(ptr) {}
+ ~SharedPtrDeletionImpl() {
+ // Checks if the supplied type is not just a plain
+ // forward definition, taken from boost::checked_delete
+ // This makes the user really aware what he tries to do
+ // when using this with an incomplete type.
+ typedef char completeCheck[sizeof(T) ? 1 : -1];
+ (void)sizeof(completeCheck);
+ delete _ptr;
+ }
+private:
+ T *_ptr;
+};
+
+template<class T, class D>
+class SharedPtrDeletionDeleterImpl : public SharedPtrDeletionInternal {
+public:
+ SharedPtrDeletionDeleterImpl(T *ptr, D d) : _ptr(ptr), _deleter(d) {}
+ ~SharedPtrDeletionDeleterImpl() { _deleter(_ptr); }
+private:
+ T *_ptr;
+ D _deleter;
+};
+
+/**
+ * A simple shared pointer implementation modelled after boost.
+ *
+ * This object keeps track of the assigned pointer and automatically
+ * frees it when no more SharedPtr references to it exist.
+ *
+ * To achieve that the object implements an internal reference counting.
+ * Thus you should try to avoid using the plain pointer after assigning
+ * it to a SharedPtr object for the first time. If you still use the
+ * plain pointer be sure you do not delete it on your own. You may also
+ * not use the plain pointer to create a new SharedPtr object, since that
+ * would result in a double deletion of the pointer sooner or later.
+ *
+ * Example creation:
+ * Common::SharedPtr<int> pointer(new int(1));
+ * would create a pointer to int. Later on usage via *pointer is the same
+ * as for a normal pointer. If you need to access the plain pointer value
+ * itself later on use the get method. The class also supplies a operator
+ * ->, which does the same as the -> operator on a normal pointer.
+ *
+ * Be sure you are using new to initialize the pointer you want to manage.
+ * If you do not use new for allocating, you have to supply a deleter as
+ * second parameter when creating a SharedPtr object. The deleter has to
+ * implement operator() which takes the pointer it should free as argument.
+ *
+ * Note that you have to specify the type itself not the pointer type as
+ * template parameter.
+ *
+ * When creating a SharedPtr object from a normal pointer you need a real
+ * definition of the type you want SharedPtr to manage, a simple forward
+ * definition is not enough.
+ *
+ * The class has implicit upcast support, so if you got a class B derived
+ * from class A, you can assign a pointer to B without any problems to a
+ * SharedPtr object with template parameter A. The very same applies to
+ * assignment of a SharedPtr<B> object to a SharedPtr<A> object.
+ *
+ * There are also operators != and == to compare two SharedPtr objects
+ * with compatible pointers. Comparison between a SharedPtr object and
+ * a plain pointer is only possible via SharedPtr::get.
+ */
+template<class T>
+class SharedPtr {
+#if !((__GNUC__ == 2) && (__GNUC_MINOR__ >= 95))
+ template<class T2> friend class SharedPtr;
+#endif
+public:
+ typedef int RefValue;
+ typedef T ValueType;
+ typedef T *Pointer;
+
+ SharedPtr() : _refCount(0), _deletion(0), _pointer(0) {}
+ template<class T2> explicit SharedPtr(T2 *p) : _refCount(new RefValue(1)), _deletion(new SharedPtrDeletionImpl<T2>(p)), _pointer(p) {}
+ template<class T2, class D> SharedPtr(T2 *p, D d) : _refCount(new RefValue(1)), _deletion(new SharedPtrDeletionDeleterImpl<T2, D>(p, d)), _pointer(p) {}
+
+ SharedPtr(const SharedPtr &r) : _refCount(r._refCount), _deletion(r._deletion), _pointer(r._pointer) { if (_refCount) ++(*_refCount); }
+ template<class T2> SharedPtr(const SharedPtr<T2> &r) : _refCount(r._refCount), _deletion(r._deletion), _pointer(r._pointer) { if (_refCount) ++(*_refCount); }
+
+ ~SharedPtr() { decRef(); }
+
+ SharedPtr &operator =(const SharedPtr &r) {
+ if (r._refCount)
+ ++(*r._refCount);
+ decRef();
+
+ _refCount = r._refCount;
+ _deletion = r._deletion;
+ _pointer = r._pointer;
+
+ return *this;
+ }
+
+ template<class T2>
+ SharedPtr &operator =(const SharedPtr<T2> &r) {
+ if (r._refCount)
+ ++(*r._refCount);
+ decRef();
+
+ _refCount = r._refCount;
+ _deletion = r._deletion;
+ _pointer = r._pointer;
+
+ return *this;
+ }
+
+ ValueType &operator *() const { assert(_pointer); return *_pointer; }
+ Pointer operator ->() const { assert(_pointer); return _pointer; }
+
+ /**
+ * Returns the plain pointer value. Be sure you know what you
+ * do if you are continuing to use that pointer.
+ *
+ * @return the pointer the SharedPtr object manages
+ */
+ Pointer get() const { return _pointer; }
+
+ /**
+ * Implicit conversion operator to bool for convenience, to make
+ * checks like "if (sharedPtr) ..." possible.
+ */
+ operator bool() const { return _pointer != 0; }
+
+ /**
+ * Checks if the SharedPtr object is the only object refering
+ * to the assigned pointer. This should just be used for
+ * debugging purposes.
+ */
+ bool unique() const { return refCount() == 1; }
+
+ /**
+ * Returns the number of references to the assigned pointer.
+ * This should just be used for debugging purposes.
+ */
+ RefValue refCount() const { return _refCount ? *_refCount : 0; }
+#if !((__GNUC__ == 2) && (__GNUC_MINOR__ >= 95))
+private:
+#endif
+ void decRef() {
+ if (_refCount) {
+ --(*_refCount);
+ if (!*_refCount) {
+ delete _refCount;
+ delete _deletion;
+ _deletion = 0;
+ _refCount = 0;
+ _pointer = 0;
+ }
+ }
+ }
+
+ RefValue *_refCount;
+ SharedPtrDeletionInternal *_deletion;
+ T *_pointer;
+};
+
+} // end of namespace Common
+
+template<class T1, class T2>
+bool operator ==(const Common::SharedPtr<T1> &l, const Common::SharedPtr<T2> &r) {
+ return l.get() == r.get();
+}
+
+template<class T1, class T2>
+bool operator !=(const Common::SharedPtr<T1> &l, const Common::SharedPtr<T2> &r) {
+ return l.get() != r.get();
+}
+
+
+#endif
+
+
+
Property changes on: residual/trunk/common/ptr.h
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Revision Author URL Id
Added: svn:eol-style
+ native
Added: residual/trunk/common/savefile.h
===================================================================
--- residual/trunk/common/savefile.h (rev 0)
+++ residual/trunk/common/savefile.h 2008-07-20 13:16:56 UTC (rev 33121)
@@ -0,0 +1,163 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ *
+ * Residual is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the AUTHORS
+ * 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 COMMON_SAVEFILE_H
+#define COMMON_SAVEFILE_H
+
+#include "common/noncopyable.h"
+#include "common/sys.h"
+#include "common/stream.h"
+#include "common/str.h"
+#include "common/error.h"
+
+namespace Common {
+
+/**
+ * A class which allows game engines to load game state data.
+ * That typically means "save games", but also includes things like the
+ * IQ points in Indy3.
+ */
+class InSaveFile : public SeekableReadStream {};
+
+/**
+ * A class which allows game engines to save game state data.
+ * That typically means "save games", but also includes things like the
+ * IQ points in Indy3.
+ */
+class OutSaveFile : public WriteStream {
+public:
+ /**
+ * Close this savefile, to be called right before destruction of this
+ * savefile. The idea is that this ways, I/O errors that occur
+ * during closing/flushing of the file can still be handled by the
+ * game engine.
+ *
+ * By default, this just flushes the stream.
+ */
+ virtual void finalize() {
+ flush();
+ }
+};
+
+
+/**
+ * The SaveFileManager is serving as a factory for InSaveFile
+ * and OutSaveFile objects.
+ *
+ * Engines and other code should use SaveFiles whenever they need to
+ * store data which they need to be able to retrieve again later on --
+ * i.e. typically save states, but also configuration files and similar
+ * things.
+ *
+ * While not declared as a singleton, it is effectively used as such,
+ * with OSystem::getSavefileManager returning a pointer to the single
+ * SaveFileManager instances to be used.
+ */
+class SaveFileManager : NonCopyable {
+
+protected:
+ SFMError _error;
+ String _errorDesc;
+
+ /**
+ * Set some information about the last error which occurred .
+ * @param error Code identifying the last error.
+ * @param errorDesc String describing the last error.
+ */
+ virtual void setError(SFMError error, const String &errorDesc) { _error = error; _errorDesc = errorDesc; }
+
+public:
+ virtual ~SaveFileManager() {}
+
+ /**
+ * Clears the last set error code and string.
+ */
+ virtual void clearError() { _error = SFM_NO_ERROR; _errorDesc = ""; }
+
+ /**
+ * Returns the last occurred error code. If none occurred, returns SFM_NO_ERROR.
+ *
+ * @return A SFMError indicating the type of the last error.
+ */
+ virtual SFMError getError() { return _error; }
+
+ /**
+ * Returns the last occurred error description. If none occurred, returns 0.
+ *
+ * @return A string describing the last error.
+ */
+ virtual String getErrorDesc() { return _errorDesc; }
+
+ /**
+ * Returns the last occurred error description. If none occurred, returns 0.
+ * Also clears the last error state and description.
+ *
+ * @return A string describing the last error.
+ */
+ virtual String popErrorDesc();
+
+ /**
+ * Open the savefile with the specified name in the given directory for saving.
+ * @param name the name of the savefile
+ * @return pointer to an OutSaveFile, or NULL if an error occured.
+ */
+ virtual OutSaveFile *openForSaving(const char *name) = 0;
+
+ /**
+ * Open the file with the specified name in the given directory for loading.
+ * @param name the name of the savefile
+ * @return pointer to an InSaveFile, or NULL if an error occured.
+ */
+ virtual InSaveFile *openForLoading(const char *name) = 0;
+
+ /**
+ * Removes the given savefile from the system.
+ * @param name the name of the savefile to be removed.
+ * @return true if no error occurred, false otherwise.
+ */
+ virtual bool removeSavefile(const char *name) = 0;
+
+ /**
+ * Renames the given savefile.
+ * @param oldName Old name.
+ * @param newName New name.
+ * @return true if no error occurred. false otherwise.
+ */
+ virtual bool renameSavefile(const char *oldName, const char *newName);
+
+ /**
+ * Request a list of available savegames with a given DOS-style pattern,
+ * also known as "glob" in the UNIX world. Refer to the Common::match()
+ * function to learn about the precise pattern format.
+ * @param pattern Pattern to match. Wildcards like * or ? are available.
+ * @return list of strings for all present file names.
+ * @see Common::match
+ */
+ virtual Common::StringList listSavefiles(const char *pattern) = 0;
+};
+
+} // End of namespace Common
+
+#endif
Property changes on: residual/trunk/common/savefile.h
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Revision Author URL Id
Added: svn:eol-style
+ native
Added: residual/trunk/common/singleton.h
===================================================================
--- residual/trunk/common/singleton.h (rev 0)
+++ residual/trunk/common/singleton.h 2008-07-20 13:16:56 UTC (rev 33121)
@@ -0,0 +1,98 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ *
+ * Residual is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the AUTHORS
+ * 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 COMMON_SINGLETON_H
+#define COMMON_SINGLETON_H
+
+#include "common/noncopyable.h"
+
+namespace Common {
+
+/**
+ * Generic template base class for implementing the singleton design pattern.
+ */
+template<class T>
+class Singleton : NonCopyable {
+private:
+ Singleton<T>(const Singleton<T> &);
+ Singleton<T> &operator=(const Singleton<T> &);
+
+ static T *_singleton;
+
+ /**
+ * The default object factory used by the template class Singleton.
+ * By specialising this template function, one can make a singleton use a
+ * custom object factory. For example, to support encapsulation, your
+ * singleton class might be pure virtual (or "abstract" in Java terminology),
+ * and you specialise makeInstance to return an instance of a subclass.
+ */
+ //template <class T>
+#if defined (_WIN32_WCE) || defined (_MSC_VER) || defined (__WINS__)
+//FIXME evc4 and msvc7 doesn't like it as private member
+public:
+#endif
+ static T *makeInstance() {
+ return new T();
+ }
+
+ static void destroyInstance() {
+ delete _singleton;
+ _singleton = 0;
+ }
+
+
+public:
+ static T& instance() {
+ // TODO: We aren't thread safe. For now we ignore it since the
+ // only thing using this singleton template is the config manager,
+ // and that is first instantiated long before any threads.
+ // TODO: We don't leak, but the destruction order is nevertheless
+ // semi-random. If we use multiple singletons, the destruction
+ // order might become an issue. There are various approaches
+ // to solve that problem, but for now this is sufficient
+ if (!_singleton)
+ _singleton = T::makeInstance();
+ return *_singleton;
+ }
+
+ static void destroy() {
+ T::destroyInstance();
+ }
+protected:
+ Singleton<T>() { }
+#ifdef __SYMBIAN32__
+ virtual ~Singleton() { }
+#else
+ virtual ~Singleton<T>() { }
+#endif
+
+ typedef T SingletonBaseType;
+};
+
+#define DECLARE_SINGLETON(T) template<> T *Common::Singleton<T>::_singleton = 0
+
+} // End of namespace Common
+
+#endif
Property changes on: residual/trunk/common/singleton.h
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Revision Author URL Id
Added: svn:eol-style
+ native
Added: residual/trunk/common/stream.cpp
===================================================================
--- residual/trunk/common/stream.cpp (rev 0)
+++ residual/trunk/common/stream.cpp 2008-07-20 13:16:56 UTC (rev 33121)
@@ -0,0 +1,190 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ *
+ * Residual is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the AUTHORS
+ * 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/stream.h"
+#include "common/str.h"
+#include "common/util.h"
+
+namespace Common {
+
+void WriteStream::writeString(const String &str) {
+ write(str.c_str(), str.size());
+}
+
+MemoryReadStream *ReadStream::readStream(uint32 dataSize) {
+ void *buf = malloc(dataSize);
+ dataSize = read(buf, dataSize);
+ assert(dataSize > 0);
+ return new MemoryReadStream((byte *)buf, dataSize, true);
+}
+
+
+uint32 MemoryReadStream::read(void *dataPtr, uint32 dataSize) {
+ // Read at most as many bytes as are still available...
+ if (dataSize > _size - _pos)
+ dataSize = _size - _pos;
+ memcpy(dataPtr, _ptr, dataSize);
+
+ if (_encbyte) {
+ byte *p = (byte *)dataPtr;
+ byte *end = p + dataSize;
+ while (p < end)
+ *p++ ^= _encbyte;
+ }
+
+ _ptr += dataSize;
+ _pos += dataSize;
+
+ return dataSize;
+}
+
+void MemoryReadStream::seek(int32 offs, int whence) {
+ // Pre-Condition
+ assert(_pos <= _size);
+ switch (whence) {
+ case SEEK_END:
+ // SEEK_END works just like SEEK_SET, only 'reversed',
+ // i.e. from the end.
+ offs = _size - offs;
+ // Fall through
+ case SEEK_SET:
+ _ptr = _ptrOrig + offs;
+ _pos = offs;
+ break;
+
+ case SEEK_CUR:
+ _ptr += offs;
+ _pos += offs;
+ break;
+ }
+ // Post-Condition
+ assert(_pos <= _size);
+}
+
+#define LF 0x0A
+#define CR 0x0D
+
+char *SeekableReadStream::readLine(char *buf, size_t bufSize) {
+ assert(buf && bufSize > 0);
+ char *p = buf;
+ size_t len = 0;
+ char c;
+
+ if (buf == 0 || bufSize == 0 || eos()) {
+ return 0;
+ }
+
+ // We don't include the newline character(s) in the buffer, and we
+ // always terminate it - we never read more than len-1 characters.
+
+ // EOF is treated as a line break, unless it was the first character
+ // that was read.
+
+ // 0 is treated as a line break, even though it should never occur in
+ // a text file.
+
+ // DOS and Windows use CRLF line breaks
+ // Unix and OS X use LF line breaks
+ // Macintosh before OS X uses CR line breaks
+
+
+ c = readByte();
+ if (eos() || ioFailed()) {
+ return 0;
+ }
+
+ while (!eos() && len + 1 < bufSize) {
+
+ if (ioFailed())
+ return 0;
+
+ if (c == 0 || c == LF)
+ break;
+
+ if (c == CR) {
+ c = readByte();
+ if (c != LF && !eos())
+ seek(-1, SEEK_CUR);
+ break;
+ }
+
+ *p++ = c;
+ len++;
+
+ c = readByte();
+ }
+
+ // This should fix a bug while using readLine with Common::File
+ // it seems that it sets the eos flag after an invalid read
+ // and at the same time the ioFailed flag
+ // the config file parser fails out of that reason for the new themes
+ if (eos()) {
+ clearIOFailed();
+ }
+
+ *p = 0;
+ return buf;
+}
+
+uint32 SubReadStream::read(void *dataPtr, uint32 dataSize) {
+ dataSize = MIN(dataSize, _end - _pos);
+
+ dataSize = _parentStream->read(dataPtr, dataSize);
+ _pos += dataSize;
+
+ return dataSize;
+}
+
+SeekableSubReadStream::SeekableSubReadStream(SeekableReadStream *parentStream, uint32 begin, uint32 end, bool disposeParentStream)
+ : SubReadStream(parentStream, end, disposeParentStream),
+ _parentStream(parentStream),
+ _begin(begin) {
+ assert(_begin <= _end);
+ _pos = _begin;
+ _parentStream->seek(_pos);
+}
+
+void SeekableSubReadStream::seek(int32 offset, int whence) {
+ assert(_pos >= _begin);
+ assert(_pos <= _end);
+
+ switch(whence) {
+ case SEEK_END:
+ offset = size() - offset;
+ // fallthrough
+ case SEEK_SET:
+ _pos = _begin + offset;
+ break;
+ case SEEK_CUR:
+ _pos += offset;
+ }
+
+ assert(_pos >= _begin);
+ assert(_pos <= _end);
+
+ _parentStream->seek(_pos);
+}
+
+} // End of namespace Common
Property changes on: residual/trunk/common/stream.cpp
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Revision Author URL Id
Added: svn:eol-style
+ native
Added: residual/trunk/common/stream.h
===================================================================
--- residual/trunk/common/stream.h (rev 0)
+++ residual/trunk/common/stream.h 2008-07-20 13:16:56 UTC (rev 33121)
@@ -0,0 +1,548 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ *
+ * Residual is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the AUTHORS
+ * 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 COMMON_STREAM_H
+#define COMMON_STREAM_H
+
+#include "common/sys.h"
+
+namespace Common {
+
+class String;
+class MemoryReadStream;
+
+/**
+ * Virtual base class for both ReadStream and WriteStream.
+ */
+class Stream {
+public:
+ virtual ~Stream() {}
+
+ /**
+ * Returns true if any I/O failure occurred.
+ * This flag is never cleared automatically. In order to clear it,
+ * client code has to call clearIOFailed() explicitly.
+ *
+ * @todo Instead of returning a plain bool, maybe we should define
+ * a list of error codes which can be returned here.
+ */
+ virtual bool ioFailed() const { return false; }
+
+ /**
+ * Reset the I/O error status.
+ */
+ virtual void clearIOFailed() {}
+};
+
+/**
+ * Generic interface for a writable data stream.
+ */
+class WriteStream : virtual public Stream {
+public:
+ /**
+ * Write data into the stream. Subclasses must implement this
+ * method; all other write methods are implemented using it.
+ *
+ * @param dataPtr pointer to the data to be written
+ * @param dataSize number of bytes to be written
+ * @return the number of bytes which were actually written.
+ */
+ virtual uint32 write(const void *dataPtr, uint32 dataSize) = 0;
+
+ /**
+ * Commit any buffered data to the underlying channel or
+ * storage medium; unbuffered streams can use the default
+ * implementation.
+ */
+ virtual void flush() {}
+
+ // The remaining methods all have default implementations; subclasses
+ // need not (and should not) overload them.
+
+ void writeByte(byte value) {
+ write(&value, 1);
+ }
+
+ void writeSByte(int8 value) {
+ write(&value, 1);
+ }
+
+ void writeUint16LE(uint16 value) {
+ writeByte((byte)(value & 0xff));
+ writeByte((byte)(value >> 8));
+ }
+
+ void writeUint32LE(uint32 value) {
+ writeUint16LE((uint16)(value & 0xffff));
+ writeUint16LE((uint16)(value >> 16));
+ }
+
+ void writeUint16BE(uint16 value) {
+ writeByte((byte)(value >> 8));
+ writeByte((byte)(value & 0xff));
+ }
+
+ void writeUint32BE(uint32 value) {
+ writeUint16BE((uint16)(value >> 16));
+ writeUint16BE((uint16)(value & 0xffff));
+ }
+
+ void writeSint16LE(int16 value) {
+ writeUint16LE((uint16)value);
+ }
+
+ void writeSint32LE(int32 value) {
+ writeUint32LE((uint32)value);
+ }
+
+ void writeSint16BE(int16 value) {
+ writeUint16BE((uint16)value);
+ }
+
+ void writeSint32BE(int32 value) {
+ writeUint32BE((uint32)value);
+ }
+
+ void writeString(const String &str);
+};
+
+
+/**
+ * Generic interface for a readable data stream.
+ */
+class ReadStream : virtual public Stream {
+public:
+ /**
+ * Returns true if the end of the stream has been reached.
+ */
+ virtual bool eos() const = 0;
+
+ /**
+ * Read data from the stream. Subclasses must implement this
+ * method; all other read methods are implemented using it.
+ *
+ * @param dataPtr pointer to a buffer into which the data is read
+ * @param dataSize number of bytes to be read
+ * @return the number of bytes which were actually read.
+ */
+ virtual uint32 read(void *dataPtr, uint32 dataSize) = 0;
+
+
+ // The remaining methods all have default implementations; subclasses
+ // need not (and should not) overload them.
+
+ /**
+ * Read am unsigned byte from the stream and return it.
+ * Performs no error checking. The return value is undefined
+ * if a read error occurred (for which client code can check by
+ * calling ioFailed()).
+ */
+ byte readByte() {
+ byte b = 0;
+ read(&b, 1);
+ return b;
+ }
+
+ /**
+ * Read a signed byte from the stream and return it.
+ * Performs no error checking. The return value is undefined
+ * if a read error occurred (for which client code can check by
+ * calling ioFailed()).
+ */
+ int8 readSByte() {
+ int8 b = 0;
+ read(&b, 1);
+ return b;
+ }
+
+ /**
+ * Read an unsigned 16-bit word stored in little endian (LSB first) order
+ * from the stream and return it.
+ * Performs no error checking. The return value is undefined
+ * if a read error occurred (for which client code can check by
+ * calling ioFailed()).
+ */
+ uint16 readUint16LE() {
+ uint16 a = readByte();
+ uint16 b = readByte();
+ return a | (b << 8);
+ }
+
+ /**
+ * Read an unsigned 32-bit word stored in little endian (LSB first) order
+ * from the stream and return it.
+ * Performs no error checking. The return value is undefined
+ * if a read error occurred (for which client code can check by
+ * calling ioFailed()).
+ */
+ uint32 readUint32LE() {
+ uint32 a = readUint16LE();
+ uint32 b = readUint16LE();
+ return (b << 16) | a;
+ }
+
+ /**
+ * Read an unsigned 16-bit word stored in big endian (MSB first) order
+ * from the stream and return it.
+ * Performs no error checking. The return value is undefined
+ * if a read error occurred (for which client code can check by
+ * calling ioFailed()).
+ */
+ uint16 readUint16BE() {
+ uint16 b = readByte();
+ uint16 a = readByte();
+ return a | (b << 8);
+ }
+
+ /**
+ * Read an unsigned 32-bit word stored in big endian (MSB first) order
+ * from the stream and return it.
+ * Performs no error checking. The return value is undefined
+ * if a read error occurred (for which client code can check by
+ * calling ioFailed()).
+ */
+ uint32 readUint32BE() {
+ uint32 b = readUint16BE();
+ uint32 a = readUint16BE();
+ return (b << 16) | a;
+ }
+
+ /**
+ * Read a signed 16-bit word stored in little endian (LSB first) order
+ * from the stream and return it.
+ * Performs no error checking. The return value is undefined
+ * if a read error occurred (for which client code can check by
+ * calling ioFailed()).
+ */
+ int16 readSint16LE() {
+ return (int16)readUint16LE();
+ }
+
+ /**
+ * Read a signed 32-bit word stored in little endian (LSB first) order
+ * from the stream and return it.
+ * Performs no error checking. The return value is undefined
+ * if a read error occurred (for which client code can check by
+ * calling ioFailed()).
+ */
+ int32 readSint32LE() {
+ return (int32)readUint32LE();
+ }
+
+ /**
+ * Read a signed 16-bit word stored in big endian (MSB first) order
+ * from the stream and return it.
+ * Performs no error checking. The return value is undefined
+ * if a read error occurred (for which client code can check by
+ * calling ioFailed()).
+ */
+ int16 readSint16BE() {
+ return (int16)readUint16BE();
+ }
+
+ /**
+ * Read a signed 32-bit word stored in big endian (MSB first) order
+ * from the stream and return it.
+ * Performs no error checking. The return value is undefined
+ * if a read error occurred (for which client code can check by
+ * calling ioFailed()).
+ */
+ int32 readSint32BE() {
+ return (int32)readUint32BE();
+ }
+
+ /**
+ * Read the specified amount of data into a malloc'ed buffer
+ * which then is wrapped into a MemoryReadStream.
+ * The returned stream might contain less data than requested,
+ * if reading more failed.
+ */
+ MemoryReadStream *readStream(uint32 dataSize);
+
+};
+
+
+/**
+ * Interface for a seekable & readable data stream.
+ *
+ * @todo We really need better error handling here!
+ * Like seek should somehow indicate whether it failed.
+ */
+class SeekableReadStream : virtual public ReadStream {
+public:
+
+ virtual uint32 pos() const = 0;
+ virtual uint32 size() const = 0;
+
+ virtual void seek(int32 offset, int whence = SEEK_SET) = 0;
+
+ void skip(uint32 offset) { seek(offset, SEEK_CUR); }
+
+ /**
+ * Read one line of text from a CR or CR/LF terminated plain text file.
+ * This method is a rough analog of the (f)gets function.
+ *
+ * @param buf the buffer to store into
+ * @param bufSize the size of the buffer
+ * @return a pointer to the read string, or NULL if an error occurred
+ * @note The line terminator (CR or CR/LF) is stripped and not inserted
+ * into the buffer.
+ */
+ virtual char *readLine(char *buf, size_t bufSize);
+};
+
+/**
+ * SubReadStream provides access to a ReadStream restricted to the range
+ * [currentPosition, currentPosition+end).
+ * Manipulating the parent stream directly /will/ mess up a substream.
+ * Likewise, manipulating two substreams of a parent stream will cause them to
+ * step on each others toes.
+ */
+class SubReadStream : virtual public ReadStream {
+protected:
+ ReadStream *_parentStream;
+ uint32 _pos;
+ uint32 _end;
+ bool _disposeParentStream;
+public:
+ SubReadStream(ReadStream *parentStream, uint32 end, bool disposeParentStream = false)
+ : _parentStream(parentStream),
+ _pos(0),
+ _end(end),
+ _disposeParentStream(disposeParentStream) {}
+ ~SubReadStream() {
+ if (_disposeParentStream) delete _parentStream;
+ }
+
+ virtual bool eos() const { return _pos == _end; }
+ virtual uint32 read(void *dataPtr, uint32 dataSize);
+};
+
+/*
+ * SeekableSubReadStream provides access to a SeekableReadStream restricted to
+ * the range [begin, end).
+ * The same caveats apply to SeekableSubReadStream as do to SeekableReadStream.
+ */
+class SeekableSubReadStream : public SubReadStream, public SeekableReadStream {
+protected:
+ SeekableReadStream *_parentStream;
+ uint32 _begin;
+public:
+ SeekableSubReadStream(SeekableReadStream *parentStream, uint32 begin, uint32 end, bool disposeParentStream = false);
+
+ virtual uint32 pos() const { return _pos - _begin; }
+ virtual uint32 size() const { return _end - _begin; }
+
+ virtual void seek(int32 offset, int whence = SEEK_SET);
+};
+
+/**
+ * This is a wrapper around SeekableSubReadStream, but it adds non-endian
+ * read methods whose endianness is set on the stream creation.
+ */
+class SeekableSubReadStreamEndian : public SeekableSubReadStream {
+public:
+ bool _bigEndian;
+
+ SeekableSubReadStreamEndian(SeekableReadStream *parentStream, uint32 begin, uint32 end, bool bigEndian = false, bool disposeParentStream = false)
+ : SeekableSubReadStream(parentStream, begin, end, disposeParentStream), _bigEndian(bigEndian) {
+ }
+
+ inline uint16 readUint16() {
+ return (_bigEndian) ? readUint16BE() : readUint16LE();
+ }
+
+ inline uint32 readUint32() {
+ return (_bigEndian) ? readUint32BE() : readUint32LE();
+ }
+
+ inline int16 readSint16() {
+ return (int16)readUint16();
+ }
+
+ inline int32 readSint32() {
+ return (int32)readUint32();
+ }
+};
+
+
+/**
+ * Simple memory based 'stream', which implements the ReadStream interface for
+ * a plain memory block.
+ */
+class MemoryReadStream : public SeekableReadStream {
+private:
+ const byte * const _ptrOrig;
+ const byte *_ptr;
+ const uint32 _size;
+ uint32 _pos;
+ byte _encbyte;
+ bool _disposeMemory;
+
+public:
+
+ /**
+ * This constructor takes a pointer to a memory buffer and a length, and
+ * wraps it. If disposeMemory is true, the MemoryReadStream takes ownership
+ * of the buffer and hence free's it when destructed.
+ */
+ MemoryReadStream(const byte *dataPtr, uint32 dataSize, bool disposeMemory = false) :
+ _ptrOrig(dataPtr),
+ _ptr(dataPtr),
+ _size(dataSize),
+ _pos(0),
+ _encbyte(0),
+ _disposeMemory(disposeMemory) {}
+
+ ~MemoryReadStream() {
+ if (_disposeMemory)
+ free(const_cast<byte *>(_ptrOrig));
+ }
+
+ void setEnc(byte value) { _encbyte = value; }
+
+ uint32 read(void *dataPtr, uint32 dataSize);
+
+ bool eos() const { return _pos == _size; }
+ uint32 pos() const { return _pos; }
+ uint32 size() const { return _size; }
+
+ void seek(int32 offs, int whence = SEEK_SET);
+};
+
+
+/**
+ * This is a wrapper around MemoryReadStream, but it adds non-endian
+ * read methods whose endianness is set on the stream creation.
+ */
+class MemoryReadStreamEndian : public Common::MemoryReadStream {
+private:
+public:
+ bool _bigEndian;
+ MemoryReadStreamEndian(const byte *buf, uint32 len, bool bigEndian = false) : MemoryReadStream(buf, len), _bigEndian(bigEndian) {}
+
+ inline uint16 readUint16() {
+ return (_bigEndian) ? readUint16BE() : readUint16LE();
+ }
+
+ inline uint32 readUint32() {
+ return (_bigEndian) ? readUint32BE() : readUint32LE();
+ }
+
+ inline int16 readSint16() {
+ return (int16)readUint16();
+ }
+
+ inline int32 readSint32() {
+ return (int32)readUint32();
+ }
+};
+
+/**
+ * Simple memory based 'stream', which implements the WriteStream interface for
+ * a plain memory block.
+ */
+class MemoryWriteStream : public WriteStream {
+private:
+ byte *_ptr;
+ const uint32 _bufSize;
+ uint32 _pos;
+public:
+ MemoryWriteStream(byte *buf, uint32 len) : _ptr(buf), _bufSize(len), _pos(0) {}
+
+ uint32 write(const void *dataPtr, uint32 dataSize) {
+ // Write at most as many bytes as are still available...
+ if (dataSize > _bufSize - _pos)
+ dataSize = _bufSize - _pos;
+ memcpy(_ptr, dataPtr, dataSize);
+ _ptr += dataSize;
+ _pos += dataSize;
+ return dataSize;
+ }
+
+ bool eos() const { return _pos == _bufSize; }
+ uint32 pos() const { return _pos; }
+ uint32 size() const { return _bufSize; }
+};
+
+/**
+ * A sort of hybrid between MemoryWriteStream and Array classes. A stream
+ * that grows as it's written to.
+ */
+class MemoryWriteStreamDynamic : public Common::WriteStream {
+private:
+ uint32 _capacity;
+ uint32 _size;
+ byte *_ptr;
+ byte *_data;
+ uint32 _pos;
+ bool _disposeMemory;
+
+ void ensureCapacity(uint32 new_len) {
+ if (new_len <= _capacity)
+ return;
+
+ byte *old_data = _data;
+
+ _capacity = new_len + 32;
+ _data = new byte[_capacity];
+ _ptr = _data + _pos;
+
+ if (old_data) {
+ // Copy old data
+ memcpy(_data, old_data, _size);
+ delete[] old_data;
+ }
+
+ _size = new_len;
+ }
+public:
+ MemoryWriteStreamDynamic(bool disposeMemory = false) : _capacity(0), _size(0), _ptr(0), _data(0), _pos(0), _disposeMemory(disposeMemory) {}
+
+ ~MemoryWriteStreamDynamic() {
+ if (_disposeMemory)
+ delete[] _data;
+ }
+
+ uint32 write(const void *dataPtr, uint32 dataSize) {
+ ensureCapacity(_pos + dataSize);
+ memcpy(_ptr, dataPtr, dataSize);
+ _ptr += dataSize;
+ _pos += dataSize;
+ if (_pos > _size)
+ _size = _pos;
+ return dataSize;
+ }
+
+ bool eos() const { return false; }
+ uint32 pos() const { return _pos; }
+ uint32 size() const { return _size; }
+
+ byte *getData() { return _data; }
+};
+
+} // End of namespace Common
+
+#endif
Property changes on: residual/trunk/common/stream.h
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Revision Author URL Id
Added: svn:eol-style
+ native
Modified: residual/trunk/common/sys.h
===================================================================
--- residual/trunk/common/sys.h 2008-07-20 11:15:29 UTC (rev 33120)
+++ residual/trunk/common/sys.h 2008-07-20 13:16:56 UTC (rev 33121)
@@ -46,6 +46,7 @@
#pragma once
#pragma warning( disable : 4068 ) // turn off "unknown pragma" warning
#pragma warning( disable : 4244 ) // turn off "conversion type" warning
+#pragma warning( disable : 4250 ) // turn off "inherits via dominance" warning
#endif
#ifndef LOCAL_PI
Modified: residual/trunk/common/util.h
===================================================================
--- residual/trunk/common/util.h 2008-07-20 11:15:29 UTC (rev 33120)
+++ residual/trunk/common/util.h 2008-07-20 13:16:56 UTC (rev 33121)
@@ -56,5 +56,4 @@
#define round(x) ((x > 0.0) ? floor((x) + 0.5) : ceil((x) - 0.5))
#endif
-
#endif
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Scummvm-git-logs
mailing list