bool TranslationManager::openTranslationsFile(const FSNode &node, File &inFile, int depth) { if (!node.exists() || !node.isReadable() || !node.isDirectory()) return false; // Check if we can find the file in this directory // Since File::open(FSNode) makes all the needed tests, it is not really // necessary to make them here. But it avoid printing warnings. FSNode fileNode = node.getChild("translations.dat"); if (fileNode.exists() && fileNode.isReadable() && !fileNode.isDirectory()) { if (inFile.open(fileNode)) { if (checkHeader(inFile)) return true; inFile.close(); } } // Check if we exceeded the given recursion depth if (depth - 1 == -1) return false; // Otherwise look for it in sub-directories FSList fileList; if (!node.getChildren(fileList, FSNode::kListDirectoriesOnly)) return false; for (FSList::iterator i = fileList.begin(); i != fileList.end(); ++i) { if (openTranslationsFile(*i, inFile, depth == -1 ? - 1 : depth - 1)) return true; } // Not found in this directory or its sub-directories return false; }
void SearchSet::addSubDirectoriesMatching(const FSNode &directory, String origPattern, bool ignoreCase, int priority) { FSList subDirs; if (!directory.getChildren(subDirs)) return; String nextPattern, pattern; String::const_iterator sep = Common::find(origPattern.begin(), origPattern.end(), '/'); if (sep != origPattern.end()) { pattern = String(origPattern.begin(), sep); ++sep; if (sep != origPattern.end()) nextPattern = String(sep, origPattern.end()); } else { pattern = origPattern; } // TODO: The code we have for displaying all matches, which vary only in case, might // be a bit overhead, but as long as we want to display all useful information to the // user we will need to keep track of all directory names added so far. We might // want to reconsider this though. typedef HashMap<String, bool, IgnoreCase_Hash, IgnoreCase_EqualTo> MatchList; MatchList multipleMatches; MatchList::iterator matchIter; for (FSList::const_iterator i = subDirs.begin(); i != subDirs.end(); ++i) { String name = i->getName(); if (Common::matchString(name.c_str(), pattern.c_str(), ignoreCase)) { matchIter = multipleMatches.find(name); if (matchIter == multipleMatches.end()) { multipleMatches[name] = true; } else { if (matchIter->_value) { warning("Clash in case for match of pattern \"%s\" found in directory \"%s\": \"%s\"", pattern.c_str(), directory.getPath().c_str(), matchIter->_key.c_str()); matchIter->_value = false; } warning("Clash in case for match of pattern \"%s\" found in directory \"%s\": \"%s\"", pattern.c_str(), directory.getPath().c_str(), name.c_str()); } if (nextPattern.empty()) addDirectory(name, *i, priority); else addSubDirectoriesMatching(*i, nextPattern, ignoreCase, priority); } } }
void FSDirectory::cacheDirectoryRecursive(FSNode node, int depth, const String& prefix) const { if (depth <= 0) return; FSList list; node.getChildren(list, FSNode::kListAll, true); 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 (!_flat && _subDirCache.contains(lowercaseName)) { 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()); } 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()); } else { _fileCache[lowercaseName] = *it; } } } }