diff options
author | Max Horn | 2008-07-29 16:09:10 +0000 |
---|---|---|
committer | Max Horn | 2008-07-29 16:09:10 +0000 |
commit | 0be985ce833d03e4458bb4512d5bed377c13d9c7 (patch) | |
tree | 0306c88a96f5eba14268fb33cc3cb45a5c8ba51e /common | |
parent | c9051fcfbd9b1f227bf5bddd81aac478d139e358 (diff) | |
download | scummvm-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.cpp | 6 | ||||
-rw-r--r-- | common/config-manager.cpp | 8 | ||||
-rw-r--r-- | common/file.cpp | 170 | ||||
-rw-r--r-- | common/file.h | 65 | ||||
-rw-r--r-- | common/unarj.cpp | 2 | ||||
-rw-r--r-- | common/unarj.h | 2 |
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); |