diff options
author | Johannes Schickel | 2016-03-01 19:14:50 +0100 |
---|---|---|
committer | Johannes Schickel | 2016-03-01 19:16:10 +0100 |
commit | 91b5c5a413af1e2a61d3f8457deff54a75a8d754 (patch) | |
tree | 11715d349c45f973208dde5c211c86381dbca690 | |
parent | 1ae2e0594d45a43c5502e3b8e8b68aec26b64d7f (diff) | |
download | scummvm-rg350-91b5c5a413af1e2a61d3f8457deff54a75a8d754.tar.gz scummvm-rg350-91b5c5a413af1e2a61d3f8457deff54a75a8d754.tar.bz2 scummvm-rg350-91b5c5a413af1e2a61d3f8457deff54a75a8d754.zip |
COMMON: Add a method to list files to MacResManager.
-rw-r--r-- | common/macresman.cpp | 111 | ||||
-rw-r--r-- | common/macresman.h | 18 |
2 files changed, 129 insertions, 0 deletions
diff --git a/common/macresman.cpp b/common/macresman.cpp index d83bde8fd8..e28bd963df 100644 --- a/common/macresman.cpp +++ b/common/macresman.cpp @@ -29,6 +29,7 @@ #include "common/md5.h" #include "common/substream.h" #include "common/textconsole.h" +#include "common/archive.h" #ifdef MACOSX #include "common/config-manager.h" @@ -261,6 +262,76 @@ bool MacResManager::exists(const String &fileName) { return false; } +void MacResManager::listFiles(Array<String> &files, const String &pattern) { + // Base names discovered so far. + typedef HashMap<String, bool, IgnoreCase_Hash, IgnoreCase_EqualTo> BaseNameSet; + BaseNameSet baseNames; + + // List files itself. + ArchiveMemberList memberList; + SearchMan.listMatchingMembers(memberList, pattern); + SearchMan.listMatchingMembers(memberList, pattern + ".rsrc"); + SearchMan.listMatchingMembers(memberList, pattern + ".bin"); + SearchMan.listMatchingMembers(memberList, constructAppleDoubleName(pattern)); + + for (ArchiveMemberList::const_iterator i = memberList.begin(), end = memberList.end(); i != end; ++i) { + String filename = (*i)->getName(); + + // For raw resource forks and MacBinary files we strip the extension + // here to obtain a valid base name. + int lastDotPos = filename.size() - 1; + for (; lastDotPos >= 0; --lastDotPos) { + if (filename[lastDotPos] == '.') { + break; + } + } + + if (lastDotPos != -1) { + const char *extension = filename.c_str() + lastDotPos + 1; + bool removeExtension = false; + + // TODO: Should we really keep filenames suggesting raw resource + // forks or MacBinary files but not being such around? This might + // depend on the pattern the client requests... + if (!scumm_stricmp(extension, "rsrc")) { + SeekableReadStream *stream = (*i)->createReadStream(); + removeExtension = stream && isRawFork(*stream); + delete stream; + } else if (!scumm_stricmp(extension, "bin")) { + SeekableReadStream *stream = (*i)->createReadStream(); + removeExtension = stream && isMacBinary(*stream); + delete stream; + } + + if (removeExtension) { + filename.erase(lastDotPos); + } + } + + // Strip AppleDouble '._' prefix if applicable. + bool isAppleDoubleName = false; + const String filenameAppleDoubleStripped = disassembleAppleDoubleName(filename, &isAppleDoubleName); + + if (isAppleDoubleName) { + SeekableReadStream *stream = (*i)->createReadStream(); + if (stream->readUint32BE() == 0x00051607) { + filename = filenameAppleDoubleStripped; + } + // TODO: Should we really keep filenames suggesting AppleDouble + // but not being AppleDouble around? This might depend on the + // pattern the client requests... + delete stream; + } + + baseNames[filename] = true; + } + + // Append resulting base names to list to indicate found files. + for (BaseNameSet::const_iterator i = baseNames.begin(), end = baseNames.end(); i != end; ++i) { + files.push_back(i->_key); + } +} + bool MacResManager::loadFromAppleDouble(SeekableReadStream &stream) { if (stream.readUint32BE() != 0x00051607) // tag return false; @@ -314,6 +385,18 @@ bool MacResManager::isMacBinary(SeekableReadStream &stream) { return true; } +bool MacResManager::isRawFork(SeekableReadStream &stream) { + // TODO: Is there a better way to detect whether this is a raw fork? + const uint32 dataOffset = stream.readUint32BE(); + const uint32 mapOffset = stream.readUint32BE(); + const uint32 dataLength = stream.readUint32BE(); + const uint32 mapLength = stream.readUint32BE(); + + return !stream.eos() && !stream.err() + && dataOffset < (uint32)stream.size() && dataOffset + dataLength <= (uint32)stream.size() + && mapOffset < (uint32)stream.size() && mapOffset + mapLength <= (uint32)stream.size(); +} + bool MacResManager::loadFromMacBinary(SeekableReadStream &stream) { byte infoHeader[MBI_INFOHDR]; stream.read(infoHeader, MBI_INFOHDR); @@ -592,4 +675,32 @@ String MacResManager::constructAppleDoubleName(String name) { return name; } +String MacResManager::disassembleAppleDoubleName(String name, bool *isAppleDouble) { + if (isAppleDouble) { + *isAppleDouble = false; + } + + // Remove "._" before the last portion of a path name. + for (int i = name.size() - 1; i >= 0; --i) { + if (i == 0) { + if (name.size() > 2 && name[0] == '.' && name[1] == '_') { + name.erase(0, 2); + if (isAppleDouble) { + *isAppleDouble = true; + } + } + } else if (name[i] == '/') { + if ((uint)(i + 2) < name.size() && name[i + 1] == '.' && name[i + 2] == '_') { + name.erase(i + 1, 2); + if (isAppleDouble) { + *isAppleDouble = true; + } + } + break; + } + } + + return name; +} + } // End of namespace Common diff --git a/common/macresman.h b/common/macresman.h index 43ec8d8e2c..5cc2542433 100644 --- a/common/macresman.h +++ b/common/macresman.h @@ -82,6 +82,16 @@ public: static bool exists(const String &fileName); /** + * List all filenames matching pattern for opening with open(). + * + * @param files Array containing all matching filenames discovered. Only + * adds to the list. + * @param pattern Pattern to match against. Taking String::matchPattern's + * format. + */ + static void listFiles(Array<String> &files, const String &pattern); + + /** * Close the Mac data/resource fork pair. */ void close(); @@ -176,6 +186,7 @@ private: bool loadFromAppleDouble(SeekableReadStream &stream); static String constructAppleDoubleName(String name); + static String disassembleAppleDoubleName(String name, bool *isAppleDouble); /** * Check if the given stream is in the MacBinary format. @@ -183,6 +194,13 @@ private: */ static bool isMacBinary(SeekableReadStream &stream); + /** + * Do a sanity check whether the given stream is a raw resource fork. + * + * @param stream Stream object to check. Will not preserve its position. + */ + static bool isRawFork(SeekableReadStream &stream); + enum { kResForkNone = 0, kResForkRaw, |