diff options
author | Max Horn | 2009-02-24 03:22:34 +0000 |
---|---|---|
committer | Max Horn | 2009-02-24 03:22:34 +0000 |
commit | d7b3c04588119eb122b23a1e923c5429492d2de5 (patch) | |
tree | d2f9eb6c0950740302b2f4a67169950610ddda4c /common/fs.cpp | |
parent | 35e33646750a7a315fd2c3fd15cdbe2ffc29131c (diff) | |
download | scummvm-rg350-d7b3c04588119eb122b23a1e923c5429492d2de5.tar.gz scummvm-rg350-d7b3c04588119eb122b23a1e923c5429492d2de5.tar.bz2 scummvm-rg350-d7b3c04588119eb122b23a1e923c5429492d2de5.zip |
Moved FSDirectory implementation from common/archive.cpp to common/fs.cpp
svn-id: r38824
Diffstat (limited to 'common/fs.cpp')
-rw-r--r-- | common/fs.cpp | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/common/fs.cpp b/common/fs.cpp index fed0669f3f..2f1347226f 100644 --- a/common/fs.cpp +++ b/common/fs.cpp @@ -163,4 +163,183 @@ Common::WriteStream *FSNode::createWriteStream() const { return _realNode->createWriteStream(); } +FSDirectory::FSDirectory(const FSNode &node, int depth) + : _node(node), _cached(false), _depth(depth) { +} + +FSDirectory::FSDirectory(const String &prefix, const FSNode &node, int depth) + : _node(node), _cached(false), _depth(depth) { + + setPrefix(prefix); +} + +FSDirectory::FSDirectory(const String &name, int depth) + : _node(name), _cached(false), _depth(depth) { +} + +FSDirectory::FSDirectory(const String &prefix, const String &name, int depth) + : _node(name), _cached(false), _depth(depth) { + + setPrefix(prefix); +} + +FSDirectory::~FSDirectory() { +} + +void FSDirectory::setPrefix(const String &prefix) { + _prefix = prefix; + + if (!_prefix.empty() && !_prefix.hasSuffix("/")) + _prefix += "/"; +} + +FSNode FSDirectory::getFSNode() const { + return _node; +} + +FSNode *FSDirectory::lookupCache(NodeCache &cache, const String &name) const { + // make caching as lazy as possible + if (!name.empty()) { + ensureCached(); + + if (cache.contains(name)) + return &cache[name]; + } + + return 0; +} + +bool FSDirectory::hasFile(const String &name) { + if (name.empty() || !_node.isDirectory()) + return false; + + FSNode *node = lookupCache(_fileCache, name); + return node && node->exists(); +} + +ArchiveMemberPtr FSDirectory::getMember(const String &name) { + if (name.empty() || !_node.isDirectory()) + return ArchiveMemberPtr(); + + FSNode *node = lookupCache(_fileCache, name); + + if (!node || !node->exists()) { + warning("FSDirectory::getMember: FSNode does not exist"); + return ArchiveMemberPtr(); + } else if (node->isDirectory()) { + warning("FSDirectory::getMember: FSNode is a directory"); + return ArchiveMemberPtr(); + } + + return ArchiveMemberPtr(new FSNode(*node)); +} + +SeekableReadStream *FSDirectory::createReadStreamForMember(const String &name) const { + if (name.empty() || !_node.isDirectory()) + return 0; + + FSNode *node = lookupCache(_fileCache, name); + if (!node) + return 0; + SeekableReadStream *stream = node->createReadStream(); + if (!stream) + warning("FSDirectory::createReadStreamForMember: Can't create stream for file '%s'", name.c_str()); + + return stream; +} + +FSDirectory *FSDirectory::getSubDirectory(const String &name, int depth) { + return getSubDirectory(String::emptyString, name, depth); +} + +FSDirectory *FSDirectory::getSubDirectory(const String &prefix, const String &name, int depth) { + if (name.empty() || !_node.isDirectory()) + return 0; + + FSNode *node = lookupCache(_subDirCache, name); + if (!node) + return 0; + + return new FSDirectory(prefix, *node, depth); +} + +void FSDirectory::cacheDirectoryRecursive(FSNode node, int depth, const String& prefix) const { + if (depth <= 0) + return; + + FSList list; + node.getChildren(list, FSNode::kListAll, false); + + FSList::iterator it = list.begin(); + for ( ; it != list.end(); ++it) { + String name = prefix + it->getName(); + + // don't touch name as it might be used for warning messages + String lowercaseName = name; + lowercaseName.toLowercase(); + + // since the hashmap is case insensitive, we need to check for clashes when caching + if (it->isDirectory()) { + if (_subDirCache.contains(lowercaseName)) { + warning("FSDirectory::cacheDirectory: name clash when building cache, ignoring sub-directory '%s'", name.c_str()); + } else { + cacheDirectoryRecursive(*it, depth - 1, lowercaseName + "/"); + _subDirCache[lowercaseName] = *it; + } + } else { + if (_fileCache.contains(lowercaseName)) { + warning("FSDirectory::cacheDirectory: name clash when building cache, ignoring file '%s'", name.c_str()); + } else { + _fileCache[lowercaseName] = *it; + } + } + } + +} + +void FSDirectory::ensureCached() const { + if (_cached) + return; + cacheDirectoryRecursive(_node, _depth, _prefix); + _cached = true; +} + +int FSDirectory::listMatchingMembers(ArchiveMemberList &list, const String &pattern) { + if (!_node.isDirectory()) + return 0; + + // Cache dir data + ensureCached(); + + String lowercasePattern(pattern); + lowercasePattern.toLowercase(); + + int matches = 0; + NodeCache::iterator it = _fileCache.begin(); + for ( ; it != _fileCache.end(); ++it) { + if (it->_key.matchString(lowercasePattern, true)) { + list.push_back(ArchiveMemberPtr(new FSNode(it->_value))); + matches++; + } + } + return matches; +} + +int FSDirectory::listMembers(ArchiveMemberList &list) { + if (!_node.isDirectory()) + return 0; + + // Cache dir data + ensureCached(); + + int files = 0; + for (NodeCache::iterator it = _fileCache.begin(); it != _fileCache.end(); ++it) { + list.push_back(ArchiveMemberPtr(new FSNode(it->_value))); + ++files; + } + + return files; +} + + } // End of namespace Common |