Project: ScummVM
Revision: 34734
Author: lordhoto
Date: 03 Oct 2008 12:57:40
Changes:Committed slightly modified patch #2034983 "Case-insensitivy and directory handling for engines".
Files:modified: /scummvm/trunk/common/archive.cpp (
try)
modified: /scummvm/trunk/engines/kyra/resource_intern.h (
try)
modified: /scummvm/trunk/common/unzip.cpp (
try)
modified: /scummvm/trunk/common/archive.h (
try)
modified: /scummvm/trunk/common/unzip.h (
try)
modified: /scummvm/trunk/engines/kyra/resource_intern.cpp (
try)
Diff:
| ... | ...@@ -30,11 +30,23 @@ |
| 30 | 30 | |
| 31 | 31 | namespace Common { |
| 32 | 32 | |
| 33 | GenericArchiveMember::GenericArchiveMember(String name, Archive *parent) |
| 34 | : _parent(parent), _name(name) { |
| 35 | } |
| 36 | |
| 37 | String GenericArchiveMember::getName() const { |
| 38 | return _name; |
| 39 | } |
| 33 | 40 | |
| 34 | | int Archive::matchPattern(StringList &list, const String &pattern) { |
| 41 | SeekableReadStream *GenericArchiveMember::open() { |
| 42 | return _parent->openFile(_name); |
| 43 | } |
| 44 | |
| 45 | |
| 46 | int Archive::listMatchingMembers(ArchiveMemberList &list, const String &pattern) { |
| 35 | 47 | // Get all "names" (TODO: "files" ?) |
| 36 | | StringList allNames; |
| 37 | | getAllNames(allNames); |
| 48 | ArchiveMemberList allNames; |
| 49 | listMembers(allNames); |
| 38 | 50 | |
| 39 | 51 | int matches = 0; |
| 40 | 52 | |
| ... | ...@@ -42,9 +54,9 @@ |
| 42 | 54 | String lowercasePattern = pattern; |
| 43 | 55 | lowercasePattern.toLowercase(); |
| 44 | 56 | |
| 45 | | StringList::iterator it = allNames.begin(); |
| 57 | ArchiveMemberList::iterator it = allNames.begin(); |
| 46 | 58 | for ( ; it != allNames.end(); it++) { |
| 47 | | if (it->matchString(lowercasePattern)) { |
| 59 | if ((*it)->getName().matchString(lowercasePattern)) { |
| 48 | 60 | list.push_back(*it); |
| 49 | 61 | matches++; |
| 50 | 62 | } |
| ... | ...@@ -53,6 +65,34 @@ |
| 53 | 65 | return matches; |
| 54 | 66 | } |
| 55 | 67 | |
| 68 | /** |
| 69 | * FSDirectoryMemeber is the implementation of ArchiveMember used by |
| 70 | * by FSDirectory. It is right now a light wrapper or FSNode. |
| 71 | */ |
| 72 | class FSDirectoryMember : public ArchiveMember { |
| 73 | FSNode _node; |
| 74 | |
| 75 | public: |
| 76 | FSDirectoryMember(FSNode &node) : _node(node) { |
| 77 | } |
| 78 | |
| 79 | /* |
| 80 | NOTE/FIXME: since I assume that the only use case for getName() |
| 81 | is for error messages, I am returning the full path of the node |
| 82 | here. This seems better than we did before, when matchPattern |
| 83 | and getAllNames used to work with StringList, and we used to |
| 84 | put the relative path of the file to the list instead. |
| 85 | */ |
| 86 | String getName() const { |
| 87 | return _node.getPath(); |
| 88 | } |
| 89 | |
| 90 | SeekableReadStream *open() { |
| 91 | return _node.openForReading(); |
| 92 | } |
| 93 | }; |
| 94 | |
| 95 | typedef SharedPtr<FSDirectoryMember> FSDirectoryMemberPtr; |
| 56 | 96 | |
| 57 | 97 | FSDirectory::FSDirectory(const FSNode &node, int depth) |
| 58 | 98 | : _node(node), _cached(false), _depth(depth) { |
| ... | ...@@ -160,7 +200,7 @@ |
| 160 | 200 | |
| 161 | 201 | } |
| 162 | 202 | |
| 163 | | int FSDirectory::matchPattern(StringList &list, const String &pattern) { |
| 203 | int FSDirectory::listMatchingMembers(ArchiveMemberList &list, const String &pattern) { |
| 164 | 204 | if (!_node.isDirectory()) |
| 165 | 205 | return 0; |
| 166 | 206 | |
| ... | ...@@ -170,40 +210,25 @@ |
| 170 | 210 | _cached = true; |
| 171 | 211 | } |
| 172 | 212 | |
| 173 | | // Small optimization: Ensure the StringList has to grow at most once |
| 174 | | list.reserve(list.size() + _fileCache.size()); |
| 175 | | |
| 176 | | // Add all filenames from our cache |
| 213 | String lowercasePattern(pattern); |
| 214 | lowercasePattern.toLowercase(); |
| 215 | |
| 216 | int matches = 0; |
| 177 | 217 | NodeCache::iterator it = _fileCache.begin(); |
| 178 | 218 | for ( ; it != _fileCache.end(); it++) { |
| 179 | | if (it->_key.matchString(pattern)) |
| 180 | | list.push_back(it->_key); |
| 219 | if ((*it)._key.matchString(lowercasePattern)) { |
| 220 | list.push_back(FSDirectoryMemberPtr(new FSDirectoryMember((*it)._value))); |
| 221 | matches++; |
| 222 | } |
| 181 | 223 | } |
| 182 | | |
| 183 | | return _fileCache.size(); |
| 224 | return matches; |
| 184 | 225 | } |
| 185 | 226 | |
| 186 | | int FSDirectory::getAllNames(StringList &list) { |
| 187 | | if (!_node.isDirectory()) |
| 188 | | return 0; |
| 227 | int FSDirectory::listMembers(ArchiveMemberList &list) { |
| 228 | return listMatchingMembers(list, "*"); |
| 229 | } |
| 189 | 230 | |
| 190 | | // Cache dir data |
| 191 | | if (!_cached) { |
| 192 | | cacheDirectoryRecursive(_node, _depth, ""); |
| 193 | | _cached = true; |
| 194 | | } |
| 195 | 231 | |
| 196 | | // Small optimization: Ensure the StringList has to grow at most once |
| 197 | | list.reserve(list.size() + _fileCache.size()); |
| 198 | | |
| 199 | | // Add all filenames from our cache |
| 200 | | NodeCache::iterator it = _fileCache.begin(); |
| 201 | | for ( ; it != _fileCache.end(); it++) { |
| 202 | | list.push_back((*it)._key); |
| 203 | | } |
| 204 | | |
| 205 | | return _fileCache.size(); |
| 206 | | } |
| 207 | 232 | |
| 208 | 233 | |
| 209 | 234 | |
| ... | ...@@ -289,23 +314,23 @@ |
| 289 | 314 | return false; |
| 290 | 315 | } |
| 291 | 316 | |
| 292 | | int SearchSet::matchPattern(StringList &list, const String &pattern) { |
| 317 | int SearchSet::listMatchingMembers(ArchiveMemberList &list, const String &pattern) { |
| 293 | 318 | int matches = 0; |
| 294 | 319 | |
| 295 | 320 | ArchiveList::iterator it = _list.begin(); |
| 296 | 321 | for ( ; it != _list.end(); it++) { |
| 297 | | matches += (*it)._arc->matchPattern(list, pattern); |
| 322 | matches += (*it)._arc->listMatchingMembers(list, pattern); |
| 298 | 323 | } |
| 299 | 324 | |
| 300 | 325 | return matches; |
| 301 | 326 | } |
| 302 | 327 | |
| 303 | | int SearchSet::getAllNames(StringList &list) { |
| 328 | int SearchSet::listMembers(ArchiveMemberList &list) { |
| 304 | 329 | int matches = 0; |
| 305 | 330 | |
| 306 | 331 | ArchiveList::iterator it = _list.begin(); |
| 307 | 332 | for ( ; it != _list.end(); it++) { |
| 308 | | matches += (*it)._arc->getAllNames(list); |
| 333 | matches += (*it)._arc->listMembers(list); |
| 309 | 334 | } |
| 310 | 335 | |
| 311 | 336 | return matches; |
| ... | ...@@ -50,7 +50,7 @@ |
| 50 | 50 | PlainArchive(Resource *owner, const Common::String &filename, const FileInputList &files); |
| 51 | 51 | |
| 52 | 52 | bool hasFile(const Common::String &name); |
| 53 | | int getAllNames(Common::StringList &list); |
| 53 | int listMembers(Common::ArchiveMemberList &list); |
| 54 | 54 | Common::SeekableReadStream *openFile(const Common::String &name); |
| 55 | 55 | private: |
| 56 | 56 | struct Entry { |
| ... | ...@@ -80,7 +80,7 @@ |
| 80 | 80 | ~CachedArchive(); |
| 81 | 81 | |
| 82 | 82 | bool hasFile(const Common::String &name); |
| 83 | | int getAllNames(Common::StringList &list); |
| 83 | int listMembers(Common::ArchiveMemberList &list); |
| 84 | 84 | Common::SeekableReadStream *openFile(const Common::String &name); |
| 85 | 85 | private: |
| 86 | 86 | struct Entry { |
| ... | ...@@ -1392,26 +1392,6 @@ |
| 1392 | 1392 | return (_zipFile && unzLocateFile(_zipFile, name.c_str(), 2) == UNZ_OK); |
| 1393 | 1393 | } |
| 1394 | 1394 | |
| 1395 | | int ZipArchive::getAllNames(Common::StringList &list) { |
| 1396 | | if (!_zipFile) |
| 1397 | | return 0; |
| 1398 | | |
| 1399 | | if (unzGoToFirstFile(_zipFile) != UNZ_OK) |
| 1400 | | return 0; |
| 1401 | | |
| 1402 | | char fileNameBuffer[UNZ_MAXFILENAMEINZIP + 1]; |
| 1403 | | int fileCount = 0; |
| 1404 | | |
| 1405 | | do { |
| 1406 | | unzGetCurrentFileInfo(_zipFile, 0, fileNameBuffer, UNZ_MAXFILENAMEINZIP + 1, 0, 0, 0, 0); |
| 1407 | | list.push_back(Common::String(fileNameBuffer)); |
| 1408 | | fileCount++; |
| 1409 | | } while (unzGoToNextFile(_zipFile) == UNZ_OK); |
| 1410 | | |
| 1411 | | return fileCount; |
| 1412 | | } |
| 1413 | | |
| 1414 | | /* |
| 1415 | 1395 | int ZipArchive::listMembers(Common::ArchiveMemberList &list) { |
| 1416 | 1396 | if (!_zipFile) |
| 1417 | 1397 | return 0; |
| ... | ...@@ -1424,14 +1404,13 @@ |
| 1424 | 1404 | unzGetCurrentFileInfo(_zipFile, NULL, |
| 1425 | 1405 | szCurrentFileName, sizeof(szCurrentFileName)-1, |
| 1426 | 1406 | NULL, 0, NULL, 0); |
| 1427 | | |
| 1428 | | szCurrentFileName |
| 1407 | list.push_back(ArchiveMemberList::value_type(new GenericArchiveMember(szCurrentFileName, this))); |
| 1429 | 1408 | matches++; |
| 1430 | | err = unzGoToNextFile(file); |
| 1409 | err = unzGoToNextFile(_zipFile); |
| 1431 | 1410 | } |
| 1432 | | return 0; |
| 1411 | |
| 1412 | return matches; |
| 1433 | 1413 | } |
| 1434 | | */ |
| 1435 | 1414 | |
| 1436 | 1415 | Common::SeekableReadStream *ZipArchive::openFile(const Common::String &name) { |
| 1437 | 1416 | if (!_zipFile) |
| ... | ...@@ -36,6 +36,35 @@ |
| 36 | 36 | |
| 37 | 37 | namespace Common { |
| 38 | 38 | |
| 39 | class ArchiveMember { |
| 40 | public: |
| 41 | virtual ~ArchiveMember() { } |
| 42 | virtual String getName() const = 0; |
| 43 | virtual SeekableReadStream *open() = 0; |
| 44 | }; |
| 45 | |
| 46 | typedef List<SharedPtr<ArchiveMember> > ArchiveMemberList; |
| 47 | |
| 48 | class Archive; |
| 49 | |
| 50 | /** |
| 51 | * Simple ArchiveMemeber implementation which allows |
| 52 | * creation of ArchiveMember compatible objects via |
| 53 | * a simple Archive and name pair. |
| 54 | * |
| 55 | * Note that GenericArchiveMember objects will not |
| 56 | * be working anymore after the 'parent' object |
| 57 | * is destroyed. |
| 58 | */ |
| 59 | class GenericArchiveMember : public ArchiveMember { |
| 60 | Archive *_parent; |
| 61 | String _name; |
| 62 | public: |
| 63 | GenericArchiveMember(String name, Archive *parent); |
| 64 | String getName() const; |
| 65 | SeekableReadStream *open(); |
| 66 | }; |
| 67 | |
| 39 | 68 | /** |
| 40 | 69 | * FilePtr is a convenient way to keep track of a SeekableReadStream without |
| 41 | 70 | * having to worry about releasing its memory. |
| ... | ...@@ -63,7 +92,7 @@ |
| 63 | 92 | * |
| 64 | 93 | * @return the number of names added to list |
| 65 | 94 | */ |
| 66 | | virtual int matchPattern(StringList &list, const String &pattern); |
| 95 | virtual int listMatchingMembers(ArchiveMemberList &list, const String &pattern); |
| 67 | 96 | |
| 68 | 97 | /** |
| 69 | 98 | * Add all the names present in the Archive to list. Returned |
| ... | ...@@ -72,7 +101,7 @@ |
| 72 | 101 | * |
| 73 | 102 | * @return the number of names added to list |
| 74 | 103 | */ |
| 75 | | virtual int getAllNames(StringList &list) = 0; |
| 104 | virtual int listMembers(ArchiveMemberList &list) = 0; |
| 76 | 105 | |
| 77 | 106 | /** |
| 78 | 107 | * Create a stream bound to a file in the archive. |
| ... | ...@@ -138,8 +167,8 @@ |
| 138 | 167 | FSDirectory *getSubDirectory(const String &name); |
| 139 | 168 | |
| 140 | 169 | virtual bool hasFile(const String &name); |
| 141 | | virtual int matchPattern(StringList &list, const String &pattern); |
| 142 | | virtual int getAllNames(StringList &list); |
| 170 | virtual int listMatchingMembers(ArchiveMemberList &list, const String &pattern); |
| 171 | virtual int listMembers(ArchiveMemberList &list); |
| 143 | 172 | virtual SeekableReadStream *openFile(const String &name); |
| 144 | 173 | }; |
| 145 | 174 | |
| ... | ...@@ -195,8 +224,8 @@ |
| 195 | 224 | void setPriority(const String& name, int priority); |
| 196 | 225 | |
| 197 | 226 | virtual bool hasFile(const String &name); |
| 198 | | virtual int matchPattern(StringList &list, const String &pattern); |
| 199 | | virtual int getAllNames(StringList &list); |
| 227 | virtual int listMatchingMembers(ArchiveMemberList &list, const String &pattern); |
| 228 | virtual int listMembers(ArchiveMemberList &list); |
| 200 | 229 | |
| 201 | 230 | /** |
| 202 | 231 | * Implements openFile from Archive base class. The current policy is |
| ... | ...@@ -44,7 +44,7 @@ |
| 44 | 44 | bool isOpen() const; |
| 45 | 45 | |
| 46 | 46 | virtual bool hasFile(const String &name); |
| 47 | | virtual int getAllNames(StringList &list); |
| 47 | virtual int listMembers(Common::ArchiveMemberList &list); |
| 48 | 48 | virtual Common::SeekableReadStream *openFile(const Common::String &name); |
| 49 | 49 | }; |
| 50 | 50 | |
| ... | ...@@ -51,11 +51,11 @@ |
| 51 | 51 | return (_files.find(name) != _files.end()); |
| 52 | 52 | } |
| 53 | 53 | |
| 54 | | int PlainArchive::getAllNames(Common::StringList &list) { |
| 54 | int PlainArchive::listMembers(Common::ArchiveMemberList &list) { |
| 55 | 55 | int count = 0; |
| 56 | 56 | |
| 57 | 57 | for (FileMap::const_iterator i = _files.begin(); i != _files.end(); ++i) { |
| 58 | | list.push_back(i->_key); |
| 58 | list.push_back(Common::ArchiveMemberList::value_type(new Common::GenericArchiveMember(i->_key, this))); |
| 59 | 59 | ++count; |
| 60 | 60 | } |
| 61 | 61 | |
| ... | ...@@ -98,11 +98,11 @@ |
| 98 | 98 | return (_files.find(name) != _files.end()); |
| 99 | 99 | } |
| 100 | 100 | |
| 101 | | int CachedArchive::getAllNames(Common::StringList &list) { |
| 101 | int CachedArchive::listMembers(Common::ArchiveMemberList &list) { |
| 102 | 102 | int count = 0; |
| 103 | 103 | |
| 104 | 104 | for (FileMap::const_iterator i = _files.begin(); i != _files.end(); ++i) { |
| 105 | | list.push_back(i->_key); |
| 105 | list.push_back(Common::ArchiveMemberList::value_type(new Common::GenericArchiveMember(i->_key, this))); |
| 106 | 106 | ++count; |
| 107 | 107 | } |
| 108 | 108 | |
To list