aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorMax Horn2008-07-29 16:09:10 +0000
committerMax Horn2008-07-29 16:09:10 +0000
commit0be985ce833d03e4458bb4512d5bed377c13d9c7 (patch)
tree0306c88a96f5eba14268fb33cc3cb45a5c8ba51e /common
parentc9051fcfbd9b1f227bf5bddd81aac478d139e358 (diff)
downloadscummvm-rg350-0be985ce833d03e4458bb4512d5bed377c13d9c7.tar.gz
scummvm-rg350-0be985ce833d03e4458bb4512d5bed377c13d9c7.tar.bz2
scummvm-rg350-0be985ce833d03e4458bb4512d5bed377c13d9c7.zip
Changed class File (and derived classes) to only support read-only access; added a new class DumpFile for writing
svn-id: r33412
Diffstat (limited to 'common')
-rw-r--r--common/config-file.cpp6
-rw-r--r--common/config-manager.cpp8
-rw-r--r--common/file.cpp170
-rw-r--r--common/file.h65
-rw-r--r--common/unarj.cpp2
-rw-r--r--common/unarj.h2
6 files changed, 137 insertions, 116 deletions
diff --git a/common/config-file.cpp b/common/config-file.cpp
index fe827e32dc..9f54c9ddde 100644
--- a/common/config-file.cpp
+++ b/common/config-file.cpp
@@ -58,7 +58,7 @@ void ConfigFile::clear() {
bool ConfigFile::loadFromFile(const String &filename) {
File file;
- if (file.open(filename, File::kFileReadMode))
+ if (file.open(filename))
return loadFromStream(file);
else
return false;
@@ -171,8 +171,8 @@ bool ConfigFile::loadFromStream(SeekableReadStream &stream) {
}
bool ConfigFile::saveToFile(const String &filename) {
- File file;
- if (file.open(filename, File::kFileWriteMode))
+ DumpFile file;
+ if (file.open(filename))
return saveToStream(file);
else
return false;
diff --git a/common/config-manager.cpp b/common/config-manager.cpp
index 59855cf6c9..b0c4b2b5ef 100644
--- a/common/config-manager.cpp
+++ b/common/config-manager.cpp
@@ -289,13 +289,9 @@ void ConfigManager::loadFile(const String &filename) {
void ConfigManager::flushToDisk() {
#ifndef __DC__
- File cfg_file;
-
-// TODO
-// if (!willwrite)
-// return;
+ DumpFile cfg_file;
- if (!cfg_file.open(_filename, File::kFileWriteMode)) {
+ if (!cfg_file.open(_filename)) {
warning("Unable to write configuration file: %s", _filename.c_str());
} else {
// First write the domains in _domainSaveOrder, in that order.
diff --git a/common/file.cpp b/common/file.cpp
index a1ea1aff77..5b465b5e01 100644
--- a/common/file.cpp
+++ b/common/file.cpp
@@ -104,7 +104,7 @@
//#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
+ #define ferror(handle) DS::std_ferror(handle)
#endif
@@ -273,26 +273,14 @@ 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());
- }
+bool File::open(const String &filename) {
+ assert(!filename.empty());
+ assert(!_handle);
_name.clear();
clearIOFailed();
@@ -300,32 +288,29 @@ bool File::open(const String &filename, AccessMode mode) {
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)) {
+ if (_filesMap && _filesMap->contains(fname)) {
fname = (*_filesMap)[fname];
debug(3, "Opening hashed: %s", fname.c_str());
- _handle = fopen(fname.c_str(), modeStr);
+ _handle = fopen(fname.c_str(), "rb");
} 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);
+ _handle = fopen(fname.c_str(), "rb");
} 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);
+ _handle = fopenNoCase(filename, x->_key, "rb");
}
}
// Last resort: try the current directory
if (_handle == NULL)
- _handle = fopenNoCase(filename, "", modeStr);
+ _handle = fopenNoCase(filename, "", "rb");
// Last last (really) resort: try looking inside the application bundle on Mac OS X for the lowercase file.
#if defined(MACOSX) || defined(IPHONE)
@@ -335,7 +320,7 @@ bool File::open(const String &filename, AccessMode mode) {
if (fileUrl) {
UInt8 buf[256];
if (CFURLGetFileSystemRepresentation(fileUrl, false, (UInt8 *)buf, 256)) {
- _handle = fopen((char *)buf, modeStr);
+ _handle = fopen((char *)buf, "rb");
}
CFRelease(fileUrl);
}
@@ -345,26 +330,15 @@ bool File::open(const String &filename, AccessMode mode) {
}
- 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
+ if (_handle == NULL)
+ debug(2, "File %s not opened", filename.c_str());
+ else
+ _name = filename;
- return true;
+ return _handle != NULL;
}
-bool File::open(const FilesystemNode &node, AccessMode mode) {
- assert(mode == kFileReadMode || mode == kFileWriteMode);
+bool File::open(const FilesystemNode &node) {
if (!node.exists()) {
warning("File::open: Trying to open a FilesystemNode which does not exist");
@@ -389,25 +363,14 @@ bool File::open(const FilesystemNode &node, AccessMode mode) {
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;
- }
+ _handle = fopen(node.getPath().c_str(), "rb");
- _name = filename;
+ if (_handle == NULL)
+ debug(2, "File %s not found", filename.c_str());
+ else
+ _name = filename;
-#ifdef DEBUG_FILE_REFCOUNT
- warning("File::open on file '%s'", _name.c_str());
-#endif
-
- return true;
+ return _handle != NULL;
}
bool File::exists(const String &filename) {
@@ -438,7 +401,7 @@ bool File::exists(const String &filename) {
//Try opening the file inside the local directory as a last resort
File tmp;
- return tmp.open(filename, kFileReadMode);
+ return tmp.open(filename);
}
void File::close() {
@@ -462,28 +425,19 @@ void File::clearIOFailed() {
}
bool File::eof() const {
- if (_handle == NULL) {
- error("File::eof: File is not open!");
- return false;
- }
+ assert(_handle);
return feof((FILE *)_handle) != 0;
}
uint32 File::pos() const {
- if (_handle == NULL) {
- error("File::pos: File is not open!");
- return 0;
- }
+ assert(_handle);
return ftell((FILE *)_handle);
}
uint32 File::size() const {
- if (_handle == NULL) {
- error("File::size: File is not open!");
- return 0;
- }
+ assert(_handle);
uint32 oldPos = ftell((FILE *)_handle);
fseek((FILE *)_handle, 0, SEEK_END);
@@ -494,10 +448,7 @@ uint32 File::size() const {
}
void File::seek(int32 offs, int whence) {
- if (_handle == NULL) {
- error("File::seek: File is not open!");
- return;
- }
+ assert(_handle);
if (fseek((FILE *)_handle, offs, whence) != 0)
clearerr((FILE *)_handle);
@@ -507,10 +458,7 @@ 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;
- }
+ assert(_handle);
if (len == 0)
return 0;
@@ -523,20 +471,62 @@ uint32 File::read(void *ptr, uint32 len) {
return real_len;
}
-uint32 File::write(const void *ptr, uint32 len) {
- if (_handle == NULL) {
- error("File::write: File is not open!");
- return 0;
- }
+
+DumpFile::DumpFile() : _handle(0) {
+}
+
+DumpFile::~DumpFile() {
+ close();
+}
+
+bool DumpFile::open(const String &filename) {
+ assert(!filename.empty());
+ assert(!_handle);
+
+ String fname(filename);
+ fname.toLowercase();
+
+ _handle = fopenNoCase(filename, "", "wb");
+
+ if (_handle == NULL)
+ debug(2, "Failed to open '%s' for writing", filename.c_str());
+
+ return _handle != NULL;
+}
+
+void DumpFile::close() {
+ if (_handle)
+ fclose((FILE *)_handle);
+ _handle = NULL;
+}
+
+bool DumpFile::isOpen() const {
+ return _handle != NULL;
+}
+
+bool DumpFile::ioFailed() const {
+ assert(_handle);
+ return ferror((FILE *)_handle) != 0;
+}
+
+void DumpFile::clearIOFailed() {
+ assert(_handle);
+ clearerr((FILE *)_handle);
+}
+
+bool DumpFile::eof() const {
+ assert(_handle);
+ return feof((FILE *)_handle) != 0;
+}
+
+uint32 DumpFile::write(const void *ptr, uint32 len) {
+ assert(_handle);
if (len == 0)
return 0;
- if ((uint32)fwrite(ptr, 1, len, (FILE *)_handle) != len) {
- _ioFailed = true;
- }
-
- return len;
+ return (uint32)fwrite(ptr, 1, len, (FILE *)_handle);
}
+
} // End of namespace Common
diff --git a/common/file.h b/common/file.h
index 8a69318128..3c2520b07c 100644
--- a/common/file.h
+++ b/common/file.h
@@ -27,6 +27,7 @@
#define COMMON_FILE_H
#include "common/scummsys.h"
+#include "common/noncopyable.h"
#include "common/str.h"
#include "common/stream.h"
@@ -34,7 +35,10 @@ class FilesystemNode;
namespace Common {
-class File : public SeekableReadStream, public WriteStream {
+/**
+ * TODO: vital to document this core class properly!!! For both users and implementors
+ */
+class File : public SeekableReadStream, public NonCopyable {
protected:
/** File handle to the actual file; 0 if no file is open. */
void *_handle;
@@ -45,19 +49,7 @@ protected:
/** 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 = "");
@@ -80,8 +72,8 @@ public:
*/
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 bool open(const String &filename);
+ virtual bool open(const FilesystemNode &node);
virtual void close();
@@ -114,9 +106,52 @@ public:
virtual uint32 size() const;
void seek(int32 offs, int whence = SEEK_SET);
uint32 read(void *dataPtr, uint32 dataSize);
+};
+
+
+/**
+ * TODO: document this class
+ *
+ * Some design ideas:
+ * - automatically drop all files into dumps/ dir? Might not be desired in all cases
+ */
+class DumpFile : public WriteStream, public NonCopyable {
+protected:
+ /** File handle to the actual file; 0 if no file is open. */
+ void *_handle;
+
+public:
+ DumpFile();
+ virtual ~DumpFile();
+
+ virtual bool open(const String &filename);
+ //virtual bool open(const FilesystemNode &node);
+
+ virtual void close();
+
+ /**
+ * Checks if the object opened a file successfully.
+ *
+ * @return: true if any file is opened, false otherwise.
+ */
+ bool isOpen() const;
+
+
+ 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;
+
uint32 write(const void *dataPtr, uint32 dataSize);
};
+
} // End of namespace Common
#endif
diff --git a/common/unarj.cpp b/common/unarj.cpp
index f3ac20c285..da88c11fc9 100644
--- a/common/unarj.cpp
+++ b/common/unarj.cpp
@@ -231,7 +231,7 @@ ArjHeader *ArjFile::readHeader() {
}
-bool ArjFile::open(const Common::String &filename, AccessMode mode) {
+bool ArjFile::open(const Common::String &filename) {
if (_isOpen)
error("Attempt to open another instance of archive");
diff --git a/common/unarj.h b/common/unarj.h
index b015999671..c8965968f6 100644
--- a/common/unarj.h
+++ b/common/unarj.h
@@ -110,7 +110,7 @@ public:
void registerArchive(const String &filename);
- bool open(const Common::String &filename, AccessMode mode = kFileReadMode);
+ bool open(const Common::String &filename);
void close();
uint32 read(void *dataPtr, uint32 dataSize);