diff options
Diffstat (limited to 'common/archive.cpp')
-rw-r--r-- | common/archive.cpp | 127 |
1 files changed, 78 insertions, 49 deletions
diff --git a/common/archive.cpp b/common/archive.cpp index 49e43a5973..40c2f01ee6 100644 --- a/common/archive.cpp +++ b/common/archive.cpp @@ -30,11 +30,23 @@ namespace Common { +GenericArchiveMember::GenericArchiveMember(String name, Archive *parent) + : _parent(parent), _name(name) { +} + +String GenericArchiveMember::getName() const { + return _name; +} + +SeekableReadStream *GenericArchiveMember::open() { + return _parent->openFile(_name); +} + -int Archive::matchPattern(StringList &list, const String &pattern) { +int Archive::listMatchingMembers(ArchiveMemberList &list, const String &pattern) { // Get all "names" (TODO: "files" ?) - StringList allNames; - getAllNames(allNames); + ArchiveMemberList allNames; + listMembers(allNames); int matches = 0; @@ -42,9 +54,9 @@ int Archive::matchPattern(StringList &list, const String &pattern) { String lowercasePattern = pattern; lowercasePattern.toLowercase(); - StringList::iterator it = allNames.begin(); + ArchiveMemberList::iterator it = allNames.begin(); for ( ; it != allNames.end(); it++) { - if (it->matchString(lowercasePattern)) { + if ((*it)->getName().matchString(lowercasePattern)) { list.push_back(*it); matches++; } @@ -53,8 +65,36 @@ int Archive::matchPattern(StringList &list, const String &pattern) { return matches; } +/** + * FSDirectoryMemeber is the implementation of ArchiveMember used by + * by FSDirectory. It is right now a light wrapper or FSNode. + */ +class FSDirectoryMember : public ArchiveMember { + FSNode _node; + +public: + FSDirectoryMember(FSNode &node) : _node(node) { + } + + /* + NOTE/FIXME: since I assume that the only use case for getName() + is for error messages, I am returning the full path of the node + here. This seems better than we did before, when matchPattern + and getAllNames used to work with StringList, and we used to + put the relative path of the file to the list instead. + */ + String getName() const { + return _node.getPath(); + } + + SeekableReadStream *open() { + return _node.openForReading(); + } +}; + +typedef SharedPtr<FSDirectoryMember> FSDirectoryMemberPtr; -FSDirectory::FSDirectory(const FilesystemNode &node, int depth) +FSDirectory::FSDirectory(const FSNode &node, int depth) : _node(node), _cached(false), _depth(depth) { } @@ -65,11 +105,11 @@ FSDirectory::FSDirectory(const String &name, int depth) FSDirectory::~FSDirectory() { } -FilesystemNode FSDirectory::getFSNode() const { +FSNode FSDirectory::getFSNode() const { return _node; } -FilesystemNode FSDirectory::lookupCache(NodeCache &cache, const String &name) { +FSNode FSDirectory::lookupCache(NodeCache &cache, const String &name) { // make caching as lazy as possible if (!name.empty()) { if (!_cached) { @@ -81,7 +121,7 @@ FilesystemNode FSDirectory::lookupCache(NodeCache &cache, const String &name) { return cache[name]; } - return FilesystemNode(); + return FSNode(); } bool FSDirectory::hasFile(const String &name) { @@ -89,7 +129,7 @@ bool FSDirectory::hasFile(const String &name) { return false; } - FilesystemNode node = lookupCache(_fileCache, name); + FSNode node = lookupCache(_fileCache, name); return node.exists(); } @@ -98,13 +138,13 @@ SeekableReadStream *FSDirectory::openFile(const String &name) { return 0; } - FilesystemNode node = lookupCache(_fileCache, name); + FSNode node = lookupCache(_fileCache, name); if (!node.exists()) { - warning("FSDirectory::openFile: FilesystemNode does not exist"); + warning("FSDirectory::openFile: FSNode does not exist"); return 0; } else if (node.isDirectory()) { - warning("FSDirectory::openFile: FilesystemNode is a directory"); + warning("FSDirectory::openFile: FSNode is a directory"); return 0; } @@ -121,17 +161,17 @@ FSDirectory *FSDirectory::getSubDirectory(const String &name) { return 0; } - FilesystemNode node = lookupCache(_subDirCache, name); + FSNode node = lookupCache(_subDirCache, name); return new FSDirectory(node); } -void FSDirectory::cacheDirectoryRecursive(FilesystemNode node, int depth, const String& prefix) { +void FSDirectory::cacheDirectoryRecursive(FSNode node, int depth, const String& prefix) { if (depth <= 0) { return; } FSList list; - node.getChildren(list, FilesystemNode::kListAll, false); + node.getChildren(list, FSNode::kListAll, false); FSList::iterator it = list.begin(); for ( ; it != list.end(); it++) { @@ -160,7 +200,7 @@ void FSDirectory::cacheDirectoryRecursive(FilesystemNode node, int depth, const } -int FSDirectory::matchPattern(StringList &list, const String &pattern) { +int FSDirectory::listMatchingMembers(ArchiveMemberList &list, const String &pattern) { if (!_node.isDirectory()) return 0; @@ -170,40 +210,25 @@ int FSDirectory::matchPattern(StringList &list, const String &pattern) { _cached = true; } - // Small optimization: Ensure the StringList has to grow at most once - list.reserve(list.size() + _fileCache.size()); - - // Add all filenames from our cache + String lowercasePattern(pattern); + lowercasePattern.toLowercase(); + + int matches = 0; NodeCache::iterator it = _fileCache.begin(); for ( ; it != _fileCache.end(); it++) { - if (it->_key.matchString(pattern)) - list.push_back(it->_key); + if ((*it)._key.matchString(lowercasePattern)) { + list.push_back(FSDirectoryMemberPtr(new FSDirectoryMember((*it)._value))); + matches++; + } } - - return _fileCache.size(); + return matches; } -int FSDirectory::getAllNames(StringList &list) { - if (!_node.isDirectory()) - return 0; +int FSDirectory::listMembers(ArchiveMemberList &list) { + return listMatchingMembers(list, "*"); +} - // Cache dir data - if (!_cached) { - cacheDirectoryRecursive(_node, _depth, ""); - _cached = true; - } - // Small optimization: Ensure the StringList has to grow at most once - list.reserve(list.size() + _fileCache.size()); - - // Add all filenames from our cache - NodeCache::iterator it = _fileCache.begin(); - for ( ; it != _fileCache.end(); it++) { - list.push_back((*it)._key); - } - - return _fileCache.size(); -} @@ -234,7 +259,7 @@ void SearchSet::insert(const Node &node) { void SearchSet::add(const String& name, ArchivePtr archive, int priority) { if (find(name) == _list.end()) { - Node node = { priority, name, archive }; + Node node(priority, name, archive); insert(node); } else { warning("SearchSet::add: archive '%s' already present", name.c_str()); @@ -289,23 +314,23 @@ bool SearchSet::hasFile(const String &name) { return false; } -int SearchSet::matchPattern(StringList &list, const String &pattern) { +int SearchSet::listMatchingMembers(ArchiveMemberList &list, const String &pattern) { int matches = 0; ArchiveList::iterator it = _list.begin(); for ( ; it != _list.end(); it++) { - matches += (*it)._arc->matchPattern(list, pattern); + matches += (*it)._arc->listMatchingMembers(list, pattern); } return matches; } -int SearchSet::getAllNames(StringList &list) { +int SearchSet::listMembers(ArchiveMemberList &list) { int matches = 0; ArchiveList::iterator it = _list.begin(); for ( ; it != _list.end(); it++) { - matches += (*it)._arc->getAllNames(list); + matches += (*it)._arc->listMembers(list); } return matches; @@ -352,6 +377,10 @@ void SearchManager::clear() { // But we give them a lower priority than the default priority (which is 0), // so that archives added by client code are searched first. g_system->addSysArchivesToSearchSet(*this, -1); + + // Add the current dir as a very last resort. + // See also bug #2137680. + add(".", ArchivePtr(new FSDirectory(".")), -2); } } // namespace Common |