aboutsummaryrefslogtreecommitdiff
path: root/common/archive.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'common/archive.cpp')
-rw-r--r--common/archive.cpp127
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