diff options
author | Stephen Kennedy | 2008-09-26 21:53:08 +0000 |
---|---|---|
committer | Stephen Kennedy | 2008-09-26 21:53:08 +0000 |
commit | a7bb113e83c88fad3a23d408caa99f918fdb610a (patch) | |
tree | 698dd9d85abaa6a20957bfb9c0e006e9dd1dc8b3 /common/file.cpp | |
parent | 11c0a3bdedcdf5eb2618b9db67b559663fb93320 (diff) | |
parent | c1385076cbc57f1a4a52946a46b3ea06ecf37f37 (diff) | |
download | scummvm-rg350-a7bb113e83c88fad3a23d408caa99f918fdb610a.tar.gz scummvm-rg350-a7bb113e83c88fad3a23d408caa99f918fdb610a.tar.bz2 scummvm-rg350-a7bb113e83c88fad3a23d408caa99f918fdb610a.zip |
Merged revisions 33452-33453,33455-33459,33463-33464,33466-33471,33473-33474,33478,33490,33492,33495-33496,33509-33512,33518-33519,33522-33527,33529-33530,33537,33541,33544,33546,33550,33552-33554,33556,33558,33561-33562,33565,33568,33570,33574,33576,33578-33581,33584-33587,33590,33596,33604-33611,33614-33615,33617-33618,33620-33621,33623,33626-33627,33632-33633,33635,33637,33639-33640,33642-33645,33648,33654-33655,33664,33667-33670,33673-33674,33678,33682,33686-33691,33693,33696,33698,33700,33703,33708,33710,33712-33714,33716,33719,33721-33723,33725-33727,33729-33730,33733,33736,33742,33754,33756,33758,33761,33763,33766,33777,33781-33788,33790,33792-33793,33795,33797,33805,33807-33812,33815-33817,33819,33822,33826,33829,33837,33839,33844,33847,33858-33861,33864,33871-33873,33875,33877-33879,33886,33889-33892,33894,33896,33900,33902-33903,33919,33928,33930,33932-33936,33938-33940,33942-33943,33948,33950,33953,33967,33973,33976,33978,33980,33985,33991,33993,33999-34000,34006,34009,34011,34013,34015,34019,34021-34023,34025,34027-34028,34030,34032-34034,34036,34038-34039,34041,34046-34048,34050-34055,34057,34059-34065,34067,34072,34074,34076,34078-34081,34084,34086-34087,34089-34090,34093,34096-34102,34104,34107,34113,34116,34119,34122,34124,34126,34128,34131-34132,34135,34138,34141,34144,34146,34149,34152-34154,34156-34157,34160,34163-34164,34169,34173,34179-34194,34196-34198,34200-34201,34205-34206,34208-34217,34219-34225,34227-34228,34234-34237,34239-34249,34251-34279,34281-34284,34286-34288,34290-34320,34323-34324,34326,34328-34329,34332,34334,34336,34338-34340,34343-34353,34356-34357,34359-34371,34373,34375,34378,34381-34382,34384-34385,34389-34391,34393-34394,34396-34397,34399-34405,34407-34409,34411,34413,34415,34417-34420,34423-34426,34428-34438,34440-34454,34456-34458,34460,34462-34469,34472,34474,34479-34481,34483-34498,34501-34505,34508,34511-34518,34520-34524,34526-34563,34566-34569,34571-34590,34592,34595-34599,34602-34603,34605,34613-34615,34617,34619-34624,34627-34628,34630-34639,34642-34649 via svnmerge from
https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk
svn-id: r34654
Diffstat (limited to 'common/file.cpp')
-rw-r--r-- | common/file.cpp | 435 |
1 files changed, 86 insertions, 349 deletions
diff --git a/common/file.cpp b/common/file.cpp index 5b465b5e01..cf396a32cd 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -23,254 +23,51 @@ * */ +#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 <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) - -#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 +#include "common/system.h" 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); - } +static Common::SearchSet *s_searchSet = 0; - // - // 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) { +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) { - if (level <= 0) +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() - : _handle(0), _ioFailed(false) { + : _handle(0) { } File::~File() { @@ -285,51 +82,21 @@ 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 = fopen(fname.c_str(), "rb"); - } 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 = fopen(fname.c_str(), "rb"); + 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, "rb"); - } - } - // Last resort: try the current directory - if (_handle == NULL) - _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) - 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, "rb"); - } - CFRelease(fileUrl); - } - CFRelease(cfFileName); - } -#endif - + FilesystemNode file(filename); + if (file.exists() && !file.isDirectory()) + _handle = file.openForReading(); } - + if (_handle == NULL) debug(2, "File %s not opened", filename.c_str()); else @@ -341,18 +108,12 @@ 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"); - return false; - } /*else if (!node.isReadable() && mode == kFileReadMode) { - warning("File::open: Trying to open an unreadable FilesystemNode object for reading"); + warning("File::open: FilesystemNode is a directory"); 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()); @@ -363,7 +124,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()); @@ -374,39 +135,24 @@ 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() { - if (_handle) - fclose((FILE *)_handle); + delete _handle; _handle = NULL; } @@ -416,59 +162,47 @@ 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::err() const { assert(_handle); - - return feof((FILE *)_handle) != 0; + return _handle->err(); } -uint32 File::pos() const { +void File::clearErr() { assert(_handle); - - return ftell((FILE *)_handle); + _handle->clearErr(); } -uint32 File::size() const { +bool File::eos() const { assert(_handle); + return _handle->eos(); +} - uint32 oldPos = ftell((FILE *)_handle); - fseek((FILE *)_handle, 0, SEEK_END); - uint32 length = ftell((FILE *)_handle); - fseek((FILE *)_handle, oldPos, SEEK_SET); - - return length; +int32 File::pos() const { + assert(_handle); + return _handle->pos(); } -void File::seek(int32 offs, int whence) { +int32 File::size() const { assert(_handle); + return _handle->size(); +} - if (fseek((FILE *)_handle, offs, whence) != 0) - clearerr((FILE *)_handle); +bool File::seek(int32 offs, int whence) { + assert(_handle); + return _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); } @@ -483,20 +217,28 @@ bool DumpFile::open(const String &filename) { assert(!filename.empty()); assert(!_handle); - String fname(filename); - fname.toLowercase(); - - _handle = fopenNoCase(filename, "", "wb"); + FilesystemNode node(filename); + return open(node); +} + +bool DumpFile::open(const FilesystemNode &node) { + assert(!_handle); + + if (node.isDirectory()) { + warning("DumpFile::open: FilesystemNode is a directory"); + return false; + } + + _handle = node.openForWriting(); if (_handle == NULL) - debug(2, "Failed to open '%s' for writing", filename.c_str()); + debug(2, "File %s not found", node.getName().c_str()); return _handle != NULL; } void DumpFile::close() { - if (_handle) - fclose((FILE *)_handle); + delete _handle; _handle = NULL; } @@ -504,29 +246,24 @@ bool DumpFile::isOpen() const { return _handle != NULL; } -bool DumpFile::ioFailed() const { +bool DumpFile::err() const { assert(_handle); - return ferror((FILE *)_handle) != 0; + return _handle->ioFailed(); } -void DumpFile::clearIOFailed() { +void DumpFile::clearErr() { assert(_handle); - clearerr((FILE *)_handle); + _handle->clearIOFailed(); } -bool DumpFile::eof() const { +uint32 DumpFile::write(const void *ptr, uint32 len) { assert(_handle); - return feof((FILE *)_handle) != 0; + return _handle->write(ptr, len); } -uint32 DumpFile::write(const void *ptr, uint32 len) { +bool DumpFile::flush() { assert(_handle); - - if (len == 0) - return 0; - - return (uint32)fwrite(ptr, 1, len, (FILE *)_handle); + return _handle->flush(); } - } // End of namespace Common |