From 8246582f5e3007a014cc22fc2840bd951e0c9b7f Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 3 Sep 2008 10:11:36 +0000 Subject: Added new StdioStream class, a thin wrapper around FILE svn-id: r34300 --- common/file.cpp | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'common/file.cpp') diff --git a/common/file.cpp b/common/file.cpp index fb837b9499..6083e5547d 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -558,4 +558,66 @@ void DumpFile::flush() { } +StdioStream::StdioStream(void *handle) : _handle(handle) { + assert(handle); +} + +StdioStream::~StdioStream() { + fclose((FILE *)_handle); +} + +bool StdioStream::ioFailed() const { + return ferror((FILE *)_handle) != 0; +} + +void StdioStream::clearIOFailed() { + clearerr((FILE *)_handle); +} + +bool StdioStream::eos() const { + return feof((FILE *)_handle) != 0; +} + +uint32 StdioStream::pos() const { + // FIXME: ftell can return -1 to indicate an error (in which case errno gets set) + // Maybe we should support that, too? + return ftell((FILE *)_handle); +} + +uint32 StdioStream::size() const { + 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 StdioStream::seek(int32 offs, int whence) { + assert(_handle); + + if (fseek((FILE *)_handle, offs, whence) != 0) + clearerr((FILE *)_handle); // FIXME: why do we call clearerr here? + + // FIXME: fseek has a return value to indicate errors; + // Maybe we should support that, too? +} + +uint32 StdioStream::read(void *ptr, uint32 len) { + return (uint32)fread((byte *)ptr, 1, len, (FILE *)_handle); +} + +uint32 StdioStream::write(const void *ptr, uint32 len) { + return (uint32)fwrite(ptr, 1, len, (FILE *)_handle); +} + +void StdioStream::flush() { + // TODO: Should check the return value of fflush, and if it is non-zero, + // check errno and set an error flag. + fflush((FILE *)_handle); +} + + + + } // End of namespace Common -- cgit v1.2.3 From 320a5dc99fa416d63a5fb8ec63c07463c80dc633 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 3 Sep 2008 11:49:02 +0000 Subject: Moved StdioStream to its own files inside backends svn-id: r34303 --- common/file.cpp | 63 --------------------------------------------------------- 1 file changed, 63 deletions(-) (limited to 'common/file.cpp') diff --git a/common/file.cpp b/common/file.cpp index 6083e5547d..cc9ae01baf 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -557,67 +557,4 @@ void DumpFile::flush() { fflush((FILE *)_handle); } - -StdioStream::StdioStream(void *handle) : _handle(handle) { - assert(handle); -} - -StdioStream::~StdioStream() { - fclose((FILE *)_handle); -} - -bool StdioStream::ioFailed() const { - return ferror((FILE *)_handle) != 0; -} - -void StdioStream::clearIOFailed() { - clearerr((FILE *)_handle); -} - -bool StdioStream::eos() const { - return feof((FILE *)_handle) != 0; -} - -uint32 StdioStream::pos() const { - // FIXME: ftell can return -1 to indicate an error (in which case errno gets set) - // Maybe we should support that, too? - return ftell((FILE *)_handle); -} - -uint32 StdioStream::size() const { - 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 StdioStream::seek(int32 offs, int whence) { - assert(_handle); - - if (fseek((FILE *)_handle, offs, whence) != 0) - clearerr((FILE *)_handle); // FIXME: why do we call clearerr here? - - // FIXME: fseek has a return value to indicate errors; - // Maybe we should support that, too? -} - -uint32 StdioStream::read(void *ptr, uint32 len) { - return (uint32)fread((byte *)ptr, 1, len, (FILE *)_handle); -} - -uint32 StdioStream::write(const void *ptr, uint32 len) { - return (uint32)fwrite(ptr, 1, len, (FILE *)_handle); -} - -void StdioStream::flush() { - // TODO: Should check the return value of fflush, and if it is non-zero, - // check errno and set an error flag. - fflush((FILE *)_handle); -} - - - - } // End of namespace Common -- cgit v1.2.3 From 5c0b91397d559f0a62412a135324f974e50a18eb Mon Sep 17 00:00:00 2001 From: Lars Persson Date: Fri, 5 Sep 2008 11:31:51 +0000 Subject: Updated Symbian OS file actions with ferror and fflush. svn-id: r34340 --- common/file.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'common/file.cpp') diff --git a/common/file.cpp b/common/file.cpp index cc9ae01baf..5c0668e06f 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -122,7 +122,8 @@ long int symbian_ftell(FILE* handle); int symbian_fseek(FILE* handle, long int offset, int whence); void symbian_clearerr(FILE* handle); - + void symbian_fflush(FILE* handle); + int symbian_ferror(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) @@ -132,6 +133,8 @@ #define ftell(handle) symbian_ftell(handle) #define fseek(handle, offset, whence) symbian_fseek(handle, offset, whence) #define clearerr(handle) symbian_clearerr(handle) + #define fflush(handle) symbian_fflush(handle) + #define ferror(handle) symbian_ferror(handle) #endif namespace Common { -- cgit v1.2.3 From 5308f12c759340577000991e5466e9dd8ae222c4 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 5 Sep 2008 11:59:33 +0000 Subject: Ported AMIGA specific file buffering 'hack' from class File to StdioStream svn-id: r34345 --- common/file.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'common/file.cpp') diff --git a/common/file.cpp b/common/file.cpp index 5c0668e06f..090606d523 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -200,9 +200,11 @@ static FILE *fopenNoCase(const String &filename, const String &directory, const #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. + // 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); -- cgit v1.2.3 From 80dd18a8207396460d482c22c679aaf42ba7fef0 Mon Sep 17 00:00:00 2001 From: Lars Persson Date: Fri, 5 Sep 2008 12:02:15 +0000 Subject: Updated filehandling for Symbian OS svn-id: r34346 --- common/file.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common/file.cpp') diff --git a/common/file.cpp b/common/file.cpp index 090606d523..a6036f83b3 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -133,7 +133,7 @@ #define ftell(handle) symbian_ftell(handle) #define fseek(handle, offset, whence) symbian_fseek(handle, offset, whence) #define clearerr(handle) symbian_clearerr(handle) - #define fflush(handle) symbian_fflush(handle) + #define fflush(handle) symbian_fflush(handle) #define ferror(handle) symbian_ferror(handle) #endif -- cgit v1.2.3 From 1cecbebc4905dcfdf4c60ff03735b9073df9e3e3 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sat, 6 Sep 2008 20:49:48 +0000 Subject: Switched class File & DumpFile to use StdioStream internally svn-id: r34391 --- common/file.cpp | 163 ++++++++++++-------------------------------------------- 1 file changed, 33 insertions(+), 130 deletions(-) (limited to 'common/file.cpp') diff --git a/common/file.cpp b/common/file.cpp index a6036f83b3..a69034ea87 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -30,6 +30,8 @@ #include "common/hash-str.h" #include +#include "backends/fs/stdiostream.h" + #if defined(MACOSX) || defined(IPHONE) #include "CoreFoundation/CoreFoundation.h" #endif @@ -41,22 +43,6 @@ #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__ @@ -69,72 +55,20 @@ // 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) #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); - void symbian_fflush(FILE* handle); - int symbian_ferror(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) - #define fflush(handle) symbian_fflush(handle) - #define ferror(handle) symbian_ferror(handle) #endif namespace Common { @@ -275,7 +209,7 @@ void File::resetDefaultDirectories() { } File::File() - : _handle(0), _ioFailed(false) { + : _handle(0) { } File::~File() { @@ -284,6 +218,7 @@ File::~File() { bool File::open(const String &filename) { + FILE *file = 0; assert(!filename.empty()); assert(!_handle); @@ -296,36 +231,36 @@ bool File::open(const String &filename) { if (_filesMap && _filesMap->contains(fname)) { fname = (*_filesMap)[fname]; debug(3, "Opening hashed: %s", fname.c_str()); - _handle = fopen(fname.c_str(), "rb"); + file = 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(), "rb"); + file = 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, "rb"); + for (; file == NULL && x != _defaultDirectories->end(); ++x) { + file = fopenNoCase(filename, x->_key, "rb"); } } // Last resort: try the current directory - if (_handle == NULL) - _handle = fopenNoCase(filename, "", "rb"); + if (file == NULL) + file = 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) - if (!_handle) { + if (!file) { 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, "rb"); + file = fopen((char *)buf, "rb"); } CFRelease(fileUrl); } @@ -334,6 +269,9 @@ bool File::open(const String &filename) { #endif } + + if (file) + _handle = new StdioStream(file); if (_handle == NULL) debug(2, "File %s not opened", filename.c_str()); @@ -368,7 +306,7 @@ bool File::open(const FilesystemNode &node) { clearIOFailed(); _name.clear(); - _handle = fopen(node.getPath().c_str(), "rb"); + _handle = node.openForReading(); if (_handle == NULL) debug(2, "File %s not found", filename.c_str()); @@ -410,8 +348,7 @@ bool File::exists(const String &filename) { } void File::close() { - if (_handle) - fclose((FILE *)_handle); + delete _handle; _handle = NULL; } @@ -421,59 +358,37 @@ bool File::isOpen() const { bool File::ioFailed() const { // TODO/FIXME: Just use ferror() here? - return _ioFailed != 0; + return !_handle || _handle->ioFailed(); } void File::clearIOFailed() { - // TODO/FIXME: Just use clearerr() here? - _ioFailed = false; + if (_handle) + _handle->clearIOFailed(); } -bool File::eof() const { +bool File::eos() const { assert(_handle); - - return feof((FILE *)_handle) != 0; + return _handle->eos(); } uint32 File::pos() const { assert(_handle); - - return ftell((FILE *)_handle); + return _handle->pos(); } uint32 File::size() const { assert(_handle); - - uint32 oldPos = ftell((FILE *)_handle); - fseek((FILE *)_handle, 0, SEEK_END); - uint32 length = ftell((FILE *)_handle); - fseek((FILE *)_handle, oldPos, SEEK_SET); - - return length; + return _handle->size(); } void File::seek(int32 offs, int whence) { assert(_handle); - - if (fseek((FILE *)_handle, offs, whence) != 0) - clearerr((FILE *)_handle); + _handle->seek(offs, whence); } uint32 File::read(void *ptr, uint32 len) { - byte *ptr2 = (byte *)ptr; - uint32 real_len; - assert(_handle); - - if (len == 0) - return 0; - - real_len = fread(ptr2, 1, len, (FILE *)_handle); - if (real_len < len) { - _ioFailed = true; - } - - return real_len; + return _handle->read(ptr, len); } @@ -491,7 +406,7 @@ bool DumpFile::open(const String &filename) { String fname(filename); fname.toLowercase(); - _handle = fopenNoCase(filename, "", "wb"); + _handle = StdioStream::makeFromPath(filename, true); if (_handle == NULL) debug(2, "Failed to open '%s' for writing", filename.c_str()); @@ -513,7 +428,7 @@ bool DumpFile::open(const FilesystemNode &node) { return false; }*/ - _handle = fopen(node.getPath().c_str(), "wb"); + _handle = node.openForWriting(); if (_handle == NULL) debug(2, "File %s not found", node.getName().c_str()); @@ -522,8 +437,7 @@ bool DumpFile::open(const FilesystemNode &node) { } void DumpFile::close() { - if (_handle) - fclose((FILE *)_handle); + delete _handle; _handle = NULL; } @@ -533,33 +447,22 @@ bool DumpFile::isOpen() const { bool DumpFile::ioFailed() const { assert(_handle); - return ferror((FILE *)_handle) != 0; + return _handle->ioFailed(); } void DumpFile::clearIOFailed() { assert(_handle); - clearerr((FILE *)_handle); -} - -bool DumpFile::eof() const { - assert(_handle); - return feof((FILE *)_handle) != 0; + _handle->clearIOFailed(); } uint32 DumpFile::write(const void *ptr, uint32 len) { assert(_handle); - - if (len == 0) - return 0; - - return (uint32)fwrite(ptr, 1, len, (FILE *)_handle); + return _handle->write(ptr, len); } void DumpFile::flush() { assert(_handle); - // TODO: Should check the return value of fflush, and if it is non-zero, - // check errno and set an error flag. - fflush((FILE *)_handle); + _handle->flush(); } } // End of namespace Common -- cgit v1.2.3 From 4fd19a33781148c298c5e5ef55f3c2e5af9ca632 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sat, 6 Sep 2008 21:04:42 +0000 Subject: Removed last traces of fopen / FILE from common/file.cpp svn-id: r34393 --- common/file.cpp | 89 ++++++++++++--------------------------------------------- 1 file changed, 18 insertions(+), 71 deletions(-) (limited to 'common/file.cpp') diff --git a/common/file.cpp b/common/file.cpp index a69034ea87..11dbdb569f 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -28,7 +28,6 @@ #include "common/hashmap.h" #include "common/util.h" #include "common/hash-str.h" -#include #include "backends/fs/stdiostream.h" @@ -36,41 +35,6 @@ #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) -#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!) - - #include "backends/fs/ds/ds-fs.h" - - // Only functions used in the ScummVM source have been defined here! - #define fopen(name, mode) DS::std_fopen(name, mode) - -#endif - -#ifdef __SYMBIAN32__ - - #define FILE void - - FILE* symbian_fopen(const char* name, const char* mode); - #define fopen(name, mode) symbian_fopen(name, mode) -#endif - namespace Common { typedef HashMap StringIntMap; @@ -81,8 +45,8 @@ typedef HashMap StringIntMap; static StringIntMap *_defaultDirectories; static StringMap *_filesMap; -static FILE *fopenNoCase(const String &filename, const String &directory, const char *mode) { - FILE *file; +static SeekableReadStream *fopenNoCase(const String &filename, const String &directory) { + SeekableReadStream *handle; String dirBuf(directory); String fileBuf(filename); @@ -102,50 +66,37 @@ static FILE *fopenNoCase(const String &filename, const String &directory, const // // Try to open the file normally // - file = fopen(pathBuf.c_str(), mode); + handle = StdioStream::makeFromPath(pathBuf, false); // // Try again, with file name converted to upper case // - if (!file) { + if (!handle) { fileBuf.toUppercase(); pathBuf = dirBuf + fileBuf; - file = fopen(pathBuf.c_str(), mode); + handle = StdioStream::makeFromPath(pathBuf, false); } // // Try again, with file name converted to lower case // - if (!file) { + if (!handle) { fileBuf.toLowercase(); pathBuf = dirBuf + fileBuf; - file = fopen(pathBuf.c_str(), mode); + handle = StdioStream::makeFromPath(pathBuf, false); } // // Try again, with file name capitalized // - if (!file) { + if (!handle) { 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); + handle = StdioStream::makeFromPath(pathBuf, false); } -#endif - return file; + return handle; } void File::addDefaultDirectory(const String &directory) { @@ -218,7 +169,6 @@ File::~File() { bool File::open(const String &filename) { - FILE *file = 0; assert(!filename.empty()); assert(!_handle); @@ -231,36 +181,36 @@ bool File::open(const String &filename) { if (_filesMap && _filesMap->contains(fname)) { fname = (*_filesMap)[fname]; debug(3, "Opening hashed: %s", fname.c_str()); - file = fopen(fname.c_str(), "rb"); + _handle = StdioStream::makeFromPath(fname, false); } 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()); - file = fopen(fname.c_str(), "rb"); + _handle = StdioStream::makeFromPath(fname, false); } else { if (_defaultDirectories) { // Try all default directories StringIntMap::const_iterator x(_defaultDirectories->begin()); - for (; file == NULL && x != _defaultDirectories->end(); ++x) { - file = fopenNoCase(filename, x->_key, "rb"); + for (; _handle == NULL && x != _defaultDirectories->end(); ++x) { + _handle = fopenNoCase(filename, x->_key); } } // Last resort: try the current directory - if (file == NULL) - file = fopenNoCase(filename, "", "rb"); + if (_handle == NULL) + _handle = fopenNoCase(filename, ""); // Last last (really) resort: try looking inside the application bundle on Mac OS X for the lowercase file. #if defined(MACOSX) || defined(IPHONE) - if (!file) { + 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)) { - file = fopen((char *)buf, "rb"); + _handle = StdioStream::makeFromPath((char *)buf, false); } CFRelease(fileUrl); } @@ -270,9 +220,6 @@ bool File::open(const String &filename) { } - if (file) - _handle = new StdioStream(file); - if (_handle == NULL) debug(2, "File %s not opened", filename.c_str()); else -- cgit v1.2.3 From 10e342e37a9ec15a131d2944da6a15356dd540d4 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sun, 7 Sep 2008 21:47:46 +0000 Subject: Made File::addDefaultDirectory(Recursive) ignore FSNodes which are not dirs / are invalid, instead of erroring out svn-id: r34430 --- common/file.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common/file.cpp') diff --git a/common/file.cpp b/common/file.cpp index 11dbdb569f..bcb62f8bb4 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -114,7 +114,7 @@ void File::addDefaultDirectory(const FilesystemNode &directory) { } void File::addDefaultDirectoryRecursive(const FilesystemNode &dir, int level, const String &prefix) { - if (level <= 0) + if (level <= 0 || !dir.exists() || !dir.isDirectory()) return; FSList fslist; -- cgit v1.2.3 From ff058e062de5d399fb27f792b41f5dfc25ddd2d3 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 8 Sep 2008 11:11:32 +0000 Subject: Switched File::open, File::addDefaultDirectory to use a SearchSet internally. Code is a lot shorter & simpler now, far less failing fopen calls (good for NDS and other ports); drawback: regressions :). Good bug hunting to everybody svn-id: r34444 --- common/file.cpp | 218 ++++++++++---------------------------------------------- 1 file changed, 37 insertions(+), 181 deletions(-) (limited to 'common/file.cpp') diff --git a/common/file.cpp b/common/file.cpp index bcb62f8bb4..ba94cb285a 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -23,140 +23,47 @@ * */ +#include "common/archive.h" #include "common/file.h" #include "common/fs.h" -#include "common/hashmap.h" #include "common/util.h" -#include "common/hash-str.h" - -#include "backends/fs/stdiostream.h" - -#if defined(MACOSX) || defined(IPHONE) -#include "CoreFoundation/CoreFoundation.h" -#endif +#include "common/system.h" namespace Common { -typedef HashMap 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 SeekableReadStream *fopenNoCase(const String &filename, const String &directory) { - SeekableReadStream *handle; - 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 - // - handle = StdioStream::makeFromPath(pathBuf, false); - - // - // Try again, with file name converted to upper case - // - if (!handle) { - fileBuf.toUppercase(); - pathBuf = dirBuf + fileBuf; - handle = StdioStream::makeFromPath(pathBuf, false); - } - - // - // Try again, with file name converted to lower case - // - if (!handle) { - fileBuf.toLowercase(); - pathBuf = dirBuf + fileBuf; - handle = StdioStream::makeFromPath(pathBuf, false); - } - - // - // Try again, with file name capitalized - // - if (!handle) { - fileBuf.toLowercase(); - fileBuf.setChar(toupper(fileBuf[0]),0); - pathBuf = dirBuf + fileBuf; - handle = StdioStream::makeFromPath(pathBuf, false); - } +static Common::SearchSet *s_searchSet = 0; - return handle; -} void File::addDefaultDirectory(const String &directory) { FilesystemNode dir(directory); addDefaultDirectoryRecursive(dir, 1); } -void File::addDefaultDirectoryRecursive(const String &directory, int level, const String &prefix) { +void File::addDefaultDirectoryRecursive(const String &directory, int level) { FilesystemNode dir(directory); - addDefaultDirectoryRecursive(dir, level, prefix); + addDefaultDirectoryRecursive(dir, level); } void File::addDefaultDirectory(const FilesystemNode &directory) { addDefaultDirectoryRecursive(directory, 1); } -void File::addDefaultDirectoryRecursive(const FilesystemNode &dir, int level, const String &prefix) { +void File::addDefaultDirectoryRecursive(const FilesystemNode &dir, int level) { if (level <= 0 || !dir.exists() || !dir.isDirectory()) 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 (!s_searchSet) { + s_searchSet = new Common::SearchSet(); + g_system->addSysArchivesToSearchSet(*s_searchSet); } - 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(); - } - } - } + Common::ArchivePtr dataArchive(new Common::FSDirectory(dir, level)); + s_searchSet->add(dir.getPath(), dataArchive, 1); } void File::resetDefaultDirectories() { - delete _defaultDirectories; - delete _filesMap; - - _defaultDirectories = 0; - _filesMap = 0; + delete s_searchSet; + s_searchSet = 0; } File::File() @@ -175,49 +82,19 @@ bool File::open(const String &filename) { _name.clear(); clearIOFailed(); - String fname(filename); - fname.toLowercase(); - - if (_filesMap && _filesMap->contains(fname)) { - fname = (*_filesMap)[fname]; - debug(3, "Opening hashed: %s", fname.c_str()); - _handle = StdioStream::makeFromPath(fname, false); - } else if (_filesMap && _filesMap->contains(fname + ".")) { + if (s_searchSet && s_searchSet->hasFile(filename)) { + debug(3, "Opening hashed: %s", filename.c_str()); + _handle = s_searchSet->openFile(filename); + } else if (s_searchSet && s_searchSet->hasFile(filename + ".")) { // 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 = StdioStream::makeFromPath(fname, false); + debug(3, "Opening hashed: %s.", filename.c_str()); + _handle = s_searchSet->openFile(filename); } 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); - } - } - // Last resort: try the current directory - if (_handle == NULL) - _handle = fopenNoCase(filename, ""); - - // 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 = StdioStream::makeFromPath((char *)buf, false); - } - CFRelease(fileUrl); - } - CFRelease(cfFileName); - } -#endif - + FilesystemNode file(filename); + if (file.exists() && !file.isDirectory()) + _handle = file.openForReading(); } if (_handle == NULL) @@ -264,34 +141,20 @@ bool File::open(const FilesystemNode &node) { } 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(); - } + if (s_searchSet && s_searchSet->hasFile(filename)) { + return true; + } else if (s_searchSet && s_searchSet->hasFile(filename + ".")) { + // WORKAROUND: Bug #1458388: "SIMON1: Game Detection fails" + // sometimes instead of "GAMEPC" we get "GAMEPC." (note trailing dot) + return true; + } else { + // Last resort: try the current directory + FilesystemNode file(filename); + if (file.exists() && !file.isDirectory()) + return true; } - - //Try opening the file inside the local directory as a last resort - File tmp; - return tmp.open(filename); + + return false; } void File::close() { @@ -350,15 +213,8 @@ bool DumpFile::open(const String &filename) { assert(!filename.empty()); assert(!_handle); - String fname(filename); - fname.toLowercase(); - - _handle = StdioStream::makeFromPath(filename, true); - - if (_handle == NULL) - debug(2, "Failed to open '%s' for writing", filename.c_str()); - - return _handle != NULL; + FilesystemNode node(filename); + return open(node); } bool DumpFile::open(const FilesystemNode &node) { -- cgit v1.2.3 From 655ce26b3f09628d9408a4d82efe3a26116999fe Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sat, 13 Sep 2008 16:51:46 +0000 Subject: Big patch changing the signature of various Stream methods (some ports may need to be slightly tweaked to fix overloading errors/warnings) svn-id: r34514 --- common/file.cpp | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) (limited to 'common/file.cpp') diff --git a/common/file.cpp b/common/file.cpp index ba94cb285a..1297775f15 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -113,13 +113,7 @@ bool File::open(const FilesystemNode &node) { } 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()); @@ -181,19 +175,19 @@ bool File::eos() const { return _handle->eos(); } -uint32 File::pos() const { +int32 File::pos() const { assert(_handle); return _handle->pos(); } -uint32 File::size() const { +int32 File::size() const { assert(_handle); return _handle->size(); } -void File::seek(int32 offs, int whence) { +bool File::seek(int32 offs, int whence) { assert(_handle); - _handle->seek(offs, whence); + return _handle->seek(offs, whence); } uint32 File::read(void *ptr, uint32 len) { @@ -223,13 +217,7 @@ bool DumpFile::open(const FilesystemNode &node) { 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; - }*/ + } _handle = node.openForWriting(); @@ -263,9 +251,9 @@ uint32 DumpFile::write(const void *ptr, uint32 len) { return _handle->write(ptr, len); } -void DumpFile::flush() { +bool DumpFile::flush() { assert(_handle); - _handle->flush(); + return _handle->flush(); } } // End of namespace Common -- cgit v1.2.3 From c8eeae8d4dffa5849a23cf963884027a7789504b Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sun, 14 Sep 2008 22:28:53 +0000 Subject: Big patch changing semantics of ReadStream::eos(): eos() now only returns true _after_ trying to read past the end of the stream. This has a large potential for regressions. Please test! svn-id: r34549 --- common/file.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'common/file.cpp') diff --git a/common/file.cpp b/common/file.cpp index 1297775f15..668c97a734 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -170,6 +170,16 @@ void File::clearIOFailed() { _handle->clearIOFailed(); } +bool File::err() const { + assert(_handle); + return _handle->err(); +} + +void File::clearErr() { + assert(_handle); + _handle->clearErr(); +} + bool File::eos() const { assert(_handle); return _handle->eos(); @@ -236,12 +246,12 @@ bool DumpFile::isOpen() const { return _handle != NULL; } -bool DumpFile::ioFailed() const { +bool DumpFile::err() const { assert(_handle); return _handle->ioFailed(); } -void DumpFile::clearIOFailed() { +void DumpFile::clearErr() { assert(_handle); _handle->clearIOFailed(); } -- cgit v1.2.3 From 5f2ceea1df3d11969e3828e3fd24cffed7203aea Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 15 Sep 2008 12:37:18 +0000 Subject: Corrected and shortened some file opening related warnings svn-id: r34556 --- common/file.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'common/file.cpp') diff --git a/common/file.cpp b/common/file.cpp index 668c97a734..cf396a32cd 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -108,10 +108,10 @@ bool File::open(const String &filename) { bool File::open(const FilesystemNode &node) { if (!node.exists()) { - warning("File::open: Trying to open a FilesystemNode which does not exist"); + warning("File::open: FilesystemNode does not exist"); return false; } else if (node.isDirectory()) { - warning("File::open: Trying to open a FilesystemNode which is a directory"); + warning("File::open: FilesystemNode is a directory"); return false; } @@ -225,7 +225,7 @@ bool DumpFile::open(const FilesystemNode &node) { assert(!_handle); if (node.isDirectory()) { - warning("File::open: Trying to open a FilesystemNode which is a directory"); + warning("DumpFile::open: FilesystemNode is a directory"); return false; } -- cgit v1.2.3