[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