unsigned int CArchiveScanner::GetArchiveCompleteChecksum(const std::string& name) const { const std::vector<std::string> &ars = GetArchives(name); unsigned int checksum = 0; for (unsigned int a = 0; a < ars.size(); a++) { checksum ^= GetSingleArchiveChecksum(ars[a]); } logOutput.Print(LOG_ARCHIVESCANNER, "archive checksum %s: %d/%u\n", name.c_str(), checksum, checksum); return checksum; }
std::vector<std::string> CArchiveScanner::GetArchives(const std::string& root, int depth) const { LOG_S(LOG_SECTION_ARCHIVESCANNER, "GetArchives: %s (depth %u)", root.c_str(), depth); // Protect against circular dependencies // (worst case depth is if all archives form one huge dependency chain) if ((unsigned)depth > archiveInfos.size()) { throw content_error("Circular dependency"); } std::vector<std::string> ret; std::string lcname = StringToLower(ArchiveFromName(root)); std::map<std::string, ArchiveInfo>::const_iterator aii = archiveInfos.find(lcname); if (aii == archiveInfos.end()) { #ifdef UNITSYNC // unresolved dep, add it, so unitsync still shows this file if (!ret.empty()) { ret.push_back(lcname); } return ret; #else throw content_error("Archive \"" + lcname + "\" not found"); #endif } // Check if this archive has been replaced while (aii->second.replaced.length() > 0) { // FIXME instead of this, call this function recursively, to get the propper error handling aii = archiveInfos.find(aii->second.replaced); if (aii == archiveInfos.end()) { throw content_error("Unknown error parsing archive replacements"); } } ret.push_back(aii->second.path + aii->second.origName); // add depth-first for (std::vector<std::string>::const_iterator i = aii->second.archiveData.GetDependencies().begin(); i != aii->second.archiveData.GetDependencies().end(); ++i) { const std::vector<std::string>& deps = GetArchives(*i, depth + 1); for (std::vector<std::string>::const_iterator j = deps.begin(); j != deps.end(); ++j) { if (std::find(ret.begin(), ret.end(), *j) == ret.end()) { // add only if this dependency is not already somewhere // in the chain (which can happen if ArchiveCache.lua has // not been written yet) so its checksum is not XOR'ed // with the running one multiple times (Get*Checksum()) ret.push_back(*j); } } } return ret; }
std::vector<std::string> CArchiveScanner::GetArchives(const std::string& root, int depth) const { logOutput.Print(LOG_ARCHIVESCANNER, "GetArchives: %s (depth %u)", root.c_str(), depth); //! Protect against circular dependencies //! (worst case depth is if all archives form one huge dependency chain) if ((unsigned)depth > archiveInfo.size()) { throw content_error("Circular dependency"); } std::vector<std::string> ret; std::string lcname = StringToLower(ArchiveFromName(root)); std::map<std::string, ArchiveInfo>::const_iterator aii = archiveInfo.find(lcname); if (aii == archiveInfo.end()) { //! unresolved dep if (!ret.empty()) { //! add anyway so we get propper error-handling (only when it is not the main-archive!) ret.push_back(lcname); } return ret; } //! Check if this archive has been replaced while (aii->second.replaced.length() > 0) { aii = archiveInfo.find(aii->second.replaced); if (aii == archiveInfo.end()) { throw content_error("Unknown error parsing archive replacements"); } } ret.push_back(aii->second.path + aii->second.origName); //! add depth-first for (std::vector<std::string>::const_iterator i = aii->second.archiveData.GetDependencies().begin(); i != aii->second.archiveData.GetDependencies().end(); ++i) { const std::vector<std::string>& dep = GetArchives(*i, depth + 1); for (std::vector<std::string>::const_iterator j = dep.begin(); j != dep.end(); ++j) { if (std::find(ret.begin(), ret.end(), *j) == ret.end()) { //! add only if this dependency is not already somewhere //! in the chain (which can happen if ArchiveCache.lua has //! not been written yet) so its checksum is not XOR'ed //! with the running one multiple times (Get*Checksum()) ret.push_back(*j); } } } return ret; }