diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/archive.cpp | 2 | ||||
-rw-r--r-- | common/archive.h | 9 | ||||
-rw-r--r-- | common/fs.cpp | 42 | ||||
-rw-r--r-- | common/fs.h | 29 |
4 files changed, 57 insertions, 25 deletions
diff --git a/common/archive.cpp b/common/archive.cpp index 7e189654a6..586f3c4fd1 100644 --- a/common/archive.cpp +++ b/common/archive.cpp @@ -115,7 +115,7 @@ void SearchSet::addDirectory(const String &name, const FSNode &dir, int priority if (!dir.exists() || !dir.isDirectory()) return; - add(name, new FSDirectory(dir, depth, flat), priority); + add(name, new FSDirectory(dir, depth, flat, _ignoreClashes), priority); } void SearchSet::addSubDirectoriesMatching(const FSNode &directory, String origPattern, bool ignoreCase, int priority, int depth, bool flat) { diff --git a/common/archive.h b/common/archive.h index d76d0c4966..2cf7555371 100644 --- a/common/archive.h +++ b/common/archive.h @@ -152,7 +152,10 @@ class SearchSet : public Archive { // Add an archive keeping the list sorted by descending priority. void insert(const Node& node); + bool _ignoreClashes; + public: + SearchSet() : _ignoreClashes(false) { } virtual ~SearchSet() { clear(); } /** @@ -247,6 +250,12 @@ public: * opening the first file encountered that matches the name. */ virtual SeekableReadStream *createReadStreamForMember(const String &name) const; + + /** + * Ignore clashes when adding directories. For more details see the corresponding parameter + * in FSDirectory documentation + */ + void setIgnoreClashes(bool ignoreClashes) { _ignoreClashes = ignoreClashes; } }; diff --git a/common/fs.cpp b/common/fs.cpp index d27de48370..89c19aaaab 100644 --- a/common/fs.cpp +++ b/common/fs.cpp @@ -168,22 +168,24 @@ bool FSNode::createDirectory() const { return _realNode->createDirectory(); } -FSDirectory::FSDirectory(const FSNode &node, int depth, bool flat) - : _node(node), _cached(false), _depth(depth), _flat(flat) { +FSDirectory::FSDirectory(const FSNode &node, int depth, bool flat, bool ignoreClashes) + : _node(node), _cached(false), _depth(depth), _flat(flat), _ignoreClashes(ignoreClashes) { } -FSDirectory::FSDirectory(const String &prefix, const FSNode &node, int depth, bool flat) - : _node(node), _cached(false), _depth(depth), _flat(flat) { +FSDirectory::FSDirectory(const String &prefix, const FSNode &node, int depth, bool flat, + bool ignoreClashes) + : _node(node), _cached(false), _depth(depth), _flat(flat), _ignoreClashes(ignoreClashes) { setPrefix(prefix); } -FSDirectory::FSDirectory(const String &name, int depth, bool flat) - : _node(name), _cached(false), _depth(depth), _flat(flat) { +FSDirectory::FSDirectory(const String &name, int depth, bool flat, bool ignoreClashes) + : _node(name), _cached(false), _depth(depth), _flat(flat), _ignoreClashes(ignoreClashes) { } -FSDirectory::FSDirectory(const String &prefix, const String &name, int depth, bool flat) - : _node(name), _cached(false), _depth(depth), _flat(flat) { +FSDirectory::FSDirectory(const String &prefix, const String &name, int depth, bool flat, + bool ignoreClashes) + : _node(name), _cached(false), _depth(depth), _flat(flat), _ignoreClashes(ignoreClashes) { setPrefix(prefix); } @@ -253,11 +255,12 @@ SeekableReadStream *FSDirectory::createReadStreamForMember(const String &name) c return stream; } -FSDirectory *FSDirectory::getSubDirectory(const String &name, int depth, bool flat) { - return getSubDirectory(String(), name, depth, flat); +FSDirectory *FSDirectory::getSubDirectory(const String &name, int depth, bool flat, bool ignoreClashes) { + return getSubDirectory(String(), name, depth, flat, ignoreClashes); } -FSDirectory *FSDirectory::getSubDirectory(const String &prefix, const String &name, int depth, bool flat) { +FSDirectory *FSDirectory::getSubDirectory(const String &prefix, const String &name, int depth, + bool flat, bool ignoreClashes) { if (name.empty() || !_node.isDirectory()) return nullptr; @@ -265,7 +268,7 @@ FSDirectory *FSDirectory::getSubDirectory(const String &prefix, const String &na if (!node) return nullptr; - return new FSDirectory(prefix, *node, depth, flat); + return new FSDirectory(prefix, *node, depth, flat, ignoreClashes); } void FSDirectory::cacheDirectoryRecursive(FSNode node, int depth, const String& prefix) const { @@ -286,17 +289,26 @@ void FSDirectory::cacheDirectoryRecursive(FSNode node, int depth, const String& // since the hashmap is case insensitive, we need to check for clashes when caching if (it->isDirectory()) { if (!_flat && _subDirCache.contains(lowercaseName)) { - warning("FSDirectory::cacheDirectory: name clash when building cache, ignoring sub-directory '%s'", name.c_str()); + // Always warn in this case as it's when there are 2 directories at the same place with different case + // That means a problem in user installation as lookups are always done case insensitive + warning("FSDirectory::cacheDirectory: name clash when building cache, ignoring sub-directory '%s'", + name.c_str()); } else { if (_subDirCache.contains(lowercaseName)) { - warning("FSDirectory::cacheDirectory: name clash when building subDirCache with subdirectory '%s'", name.c_str()); + if (!_ignoreClashes) { + warning("FSDirectory::cacheDirectory: name clash when building subDirCache with subdirectory '%s'", + name.c_str()); + } } cacheDirectoryRecursive(*it, depth - 1, _flat ? prefix : lowercaseName + "/"); _subDirCache[lowercaseName] = *it; } } else { if (_fileCache.contains(lowercaseName)) { - warning("FSDirectory::cacheDirectory: name clash when building cache, ignoring file '%s'", name.c_str()); + if (!_ignoreClashes) { + warning("FSDirectory::cacheDirectory: name clash when building cache, ignoring file '%s'", + name.c_str()); + } } else { _fileCache[lowercaseName] = *it; } diff --git a/common/fs.h b/common/fs.h index 7041428fc8..718f47ff56 100644 --- a/common/fs.h +++ b/common/fs.h @@ -267,6 +267,12 @@ public: * are cached without the relative path, so in the example above * c:\my\data\file.ext would be cached as file.ext. * + * When the 'ignoreClashes' argument to the constructor is true, name clashes are + * expected by the engine. It means that files which clash should be identical and + * getSubDirectory shouldn't be used on clashing directories. This flag is useful + * in flat mode when there are directories with same name at different places in the + * tree whose name isn't relevant for the engine code. + * * Client code can customize cache by using the constructors with the 'prefix' * parameter. In this case, the prefix is prepended to each entry in the cache, * and effectively treated as a 'virtual' parent subdirectory. FSDirectory adds @@ -276,7 +282,10 @@ public: * */ class FSDirectory : public Archive { - FSNode _node; + FSNode _node; + int _depth; + bool _flat; + bool _ignoreClashes; String _prefix; // string that is prepended to each cache item key void setPrefix(const String &prefix); @@ -286,8 +295,6 @@ class FSDirectory : public Archive { typedef HashMap<String, FSNode, IgnoreCase_Hash, IgnoreCase_EqualTo> NodeCache; mutable NodeCache _fileCache, _subDirCache; mutable bool _cached; - mutable int _depth; - mutable bool _flat; // look for a match FSNode *lookupCache(NodeCache &cache, const String &name) const; @@ -304,17 +311,19 @@ public: * unbound FSDirectory if name is not found on the filesystem or if the node is not a * valid directory. */ - FSDirectory(const String &name, int depth = 1, bool flat = false); - FSDirectory(const FSNode &node, int depth = 1, bool flat = false); + FSDirectory(const String &name, int depth = 1, bool flat = false, + bool ignoreClashes = false); + FSDirectory(const FSNode &node, int depth = 1, bool flat = false, + bool ignoreClashes = false); /** * Create a FSDirectory representing a tree with the specified depth. The parameter * prefix is prepended to the keys in the cache. See class comment. */ FSDirectory(const String &prefix, const String &name, int depth = 1, - bool flat = false); + bool flat = false, bool ignoreClashes = false); FSDirectory(const String &prefix, const FSNode &node, int depth = 1, - bool flat = false); + bool flat = false, bool ignoreClashes = false); virtual ~FSDirectory(); @@ -328,8 +337,10 @@ public: * for an explanation of the prefix parameter. * @return a new FSDirectory instance */ - FSDirectory *getSubDirectory(const String &name, int depth = 1, bool flat = false); - FSDirectory *getSubDirectory(const String &prefix, const String &name, int depth = 1, bool flat = false); + FSDirectory *getSubDirectory(const String &name, int depth = 1, bool flat = false, + bool ignoreClashes = false); + FSDirectory *getSubDirectory(const String &prefix, const String &name, int depth = 1, + bool flat = false, bool ignoreClashes = false); /** * Checks for existence in the cache. A full match of relative path and filename is needed |