void CArchiveScanner::WriteCacheData(const std::string& filename) { if (!isDirty) { return; } FILE* out = fopen(filename.c_str(), "wt"); if (!out) { return; } // First delete all outdated information // TODO: this pattern should be moved into utility function.. for (std::map<std::string, ArchiveInfo>::iterator i = archiveInfo.begin(); i != archiveInfo.end(); ) { if (!i->second.updated) { #ifdef _MSC_VER i = archiveInfo.erase(i); #else archiveInfo.erase(i++); #endif } else { ++i; } } for (std::map<std::string, BrokenArchive>::iterator i = brokenArchives.begin(); i != brokenArchives.end(); ) { if (!i->second.updated) { #ifdef _MSC_VER i = brokenArchives.erase(i); #else brokenArchives.erase(i++); #endif } else { ++i; } } fprintf(out, "local archiveCache = {\n\n"); fprintf(out, "\tinternalver = %i,\n\n", INTERNAL_VER); fprintf(out, "\tarchives = { -- count = "_STPF_"\n", archiveInfo.size()); std::map<std::string, ArchiveInfo>::const_iterator arcIt; for (arcIt = archiveInfo.begin(); arcIt != archiveInfo.end(); ++arcIt) { const ArchiveInfo& arcInfo = arcIt->second; fprintf(out, "\t\t{\n"); SafeStr(out, "\t\t\tname = ", arcInfo.origName); SafeStr(out, "\t\t\tpath = ", arcInfo.path); fprintf(out, "\t\t\tmodified = \"%u\",\n", arcInfo.modified); fprintf(out, "\t\t\tchecksum = \"%u\",\n", arcInfo.checksum); SafeStr(out, "\t\t\treplaced = ", arcInfo.replaced); // mod info? const ArchiveData& archData = arcInfo.archiveData; if (archData.name != "") { fprintf(out, "\t\t\tarchivedata = {\n"); SafeStr(out, "\t\t\t\tname = ", archData.name); SafeStr(out, "\t\t\t\tshortname = ", archData.shortName); SafeStr(out, "\t\t\t\tversion = ", archData.version); SafeStr(out, "\t\t\t\tmutator = ", archData.mutator); SafeStr(out, "\t\t\t\tgame = ", archData.game); SafeStr(out, "\t\t\t\tmapfile = ", archData.mapfile); SafeStr(out, "\t\t\t\tshortgame = ", archData.shortGame); SafeStr(out, "\t\t\t\tdescription = ", archData.description); fprintf(out, "\t\t\t\tmodtype = %d,\n", archData.modType); std::vector<std::string> deps = archData.dependencies; if (archData.modType == modtype::map) { FilterDep(deps, "Map Helper v1"); } else if (archData.modType == modtype::primary) { FilterDep(deps, "Spring content v1"); } if (!deps.empty()) { fprintf(out, "\t\t\t\tdepend = {\n"); for (unsigned d = 0; d < deps.size(); d++) { SafeStr(out, "\t\t\t\t\t", deps[d]); } fprintf(out, "\t\t\t\t},\n"); } fprintf(out, "\t\t\t},\n"); } fprintf(out, "\t\t},\n"); } fprintf(out, "\t},\n\n"); // close 'archives' fprintf(out, "\tbrokenArchives = { -- count = "_STPF_"\n", brokenArchives.size()); std::map<std::string, BrokenArchive>::const_iterator bai; for (bai = brokenArchives.begin(); bai != brokenArchives.end(); ++bai) { const BrokenArchive& ba = bai->second; fprintf(out, "\t\t{\n"); SafeStr(out, "\t\t\tname = ", bai->first); SafeStr(out, "\t\t\tpath = ", ba.path); fprintf(out, "\t\t\tmodified = \"%u\",\n", ba.modified); fprintf(out, "\t\t},\n"); } fprintf(out, "\t},\n"); // close 'brokenArchives' fprintf(out, "}\n\n"); // close 'archiveCache' fprintf(out, "return archiveCache\n"); fclose(out); isDirty = false; }
void CArchiveScanner::WriteCacheData(const std::string& filename) { if (!isDirty) { return; } FILE* out = fopen(filename.c_str(), "wt"); if (!out) { return; } // First delete all outdated information // TODO: this pattern should be moved into an utility function.. for (std::map<std::string, ArchiveInfo>::iterator i = archiveInfo.begin(); i != archiveInfo.end(); ) { if (!i->second.updated) { i = set_erase(archiveInfo, i); } else { ++i; } } for (std::map<std::string, BrokenArchive>::iterator i = brokenArchives.begin(); i != brokenArchives.end(); ) { if (!i->second.updated) { i = set_erase(brokenArchives, i); } else { ++i; } } fprintf(out, "local archiveCache = {\n\n"); fprintf(out, "\tinternalver = %i,\n\n", INTERNAL_VER); fprintf(out, "\tarchives = { -- count = "_STPF_"\n", archiveInfo.size()); std::map<std::string, ArchiveInfo>::const_iterator arcIt; for (arcIt = archiveInfo.begin(); arcIt != archiveInfo.end(); ++arcIt) { const ArchiveInfo& arcInfo = arcIt->second; fprintf(out, "\t\t{\n"); SafeStr(out, "\t\t\tname = ", arcInfo.origName); SafeStr(out, "\t\t\tpath = ", arcInfo.path); fprintf(out, "\t\t\tmodified = \"%u\",\n", arcInfo.modified); fprintf(out, "\t\t\tchecksum = \"%u\",\n", arcInfo.checksum); SafeStr(out, "\t\t\treplaced = ", arcInfo.replaced); // mod info? const ArchiveData& archData = arcInfo.archiveData; if (!archData.GetName().empty()) { fprintf(out, "\t\t\tarchivedata = {\n"); const std::map<std::string, InfoItem>& info = archData.GetInfo(); std::map<std::string, InfoItem>::const_iterator ii; for (ii = info.begin(); ii != info.end(); ++ii) { switch (ii->second.valueType) { case INFO_VALUE_TYPE_STRING: { SafeStr(out, std::string("\t\t\t\t" + ii->first + " = ").c_str(), ii->second.valueTypeString); } break; case INFO_VALUE_TYPE_INTEGER: { fprintf(out, "\t\t\t\t%s = %d,\n", ii->first.c_str(), ii->second.value.typeInteger); } break; case INFO_VALUE_TYPE_FLOAT: { fprintf(out, "\t\t\t\t%s = %f,\n", ii->first.c_str(), ii->second.value.typeFloat); } break; case INFO_VALUE_TYPE_BOOL: { fprintf(out, "\t\t\t\t%s = %d,\n", ii->first.c_str(), (int)ii->second.value.typeBool); } break; } } std::vector<std::string> deps = archData.GetDependencies(); if (archData.GetModType() == modtype::map) { FilterDep(deps, "Map Helper v1"); } else if (archData.GetModType() == modtype::primary) { FilterDep(deps, "Spring content v1"); } if (!deps.empty()) { fprintf(out, "\t\t\t\tdepend = {\n"); for (unsigned d = 0; d < deps.size(); d++) { SafeStr(out, "\t\t\t\t\t", deps[d]); } fprintf(out, "\t\t\t\t},\n"); } fprintf(out, "\t\t\t},\n"); } fprintf(out, "\t\t},\n"); } fprintf(out, "\t},\n\n"); // close 'archives' fprintf(out, "\tbrokenArchives = { -- count = "_STPF_"\n", brokenArchives.size()); std::map<std::string, BrokenArchive>::const_iterator bai; for (bai = brokenArchives.begin(); bai != brokenArchives.end(); ++bai) { const BrokenArchive& ba = bai->second; fprintf(out, "\t\t{\n"); SafeStr(out, "\t\t\tname = ", bai->first); SafeStr(out, "\t\t\tpath = ", ba.path); fprintf(out, "\t\t\tmodified = \"%u\",\n", ba.modified); SafeStr(out, "\t\t\tproblem = ", ba.problem); fprintf(out, "\t\t},\n"); } fprintf(out, "\t},\n"); // close 'brokenArchives' fprintf(out, "}\n\n"); // close 'archiveCache' fprintf(out, "return archiveCache\n"); fclose(out); isDirty = false; }
void CArchiveScanner::WriteCacheData(const std::string& filename) { std::lock_guard<spring::recursive_mutex> lck(scannerMutex); if (!isDirty) return; FILE* out = fopen(filename.c_str(), "wt"); if (out == nullptr) { LOG_L(L_ERROR, "[AS::%s] failed to write to \"%s\"!", __func__, filename.c_str()); return; } // First delete all outdated information spring::map_erase_if(archiveInfos, [](const decltype(archiveInfos)::value_type& p) { return !p.second.updated; }); spring::map_erase_if(brokenArchives, [](const decltype(brokenArchives)::value_type& p) { return !p.second.updated; }); fprintf(out, "local archiveCache = {\n\n"); fprintf(out, "\tinternalver = %i,\n\n", INTERNAL_VER); fprintf(out, "\tarchives = { -- count = %u\n", unsigned(archiveInfos.size())); for (const auto& arcIt: archiveInfos) { const ArchiveInfo& arcInfo = arcIt.second; fprintf(out, "\t\t{\n"); SafeStr(out, "\t\t\tname = ", arcInfo.origName); SafeStr(out, "\t\t\tpath = ", arcInfo.path); fprintf(out, "\t\t\tmodified = \"%u\",\n", arcInfo.modified); fprintf(out, "\t\t\tchecksum = \"%u\",\n", arcInfo.checksum); SafeStr(out, "\t\t\treplaced = ", arcInfo.replaced); // mod info? const ArchiveData& archData = arcInfo.archiveData; if (!archData.GetName().empty()) { fprintf(out, "\t\t\tarchivedata = {\n"); for (const auto& ii: archData.GetInfo()) { if (ii.second.valueType == INFO_VALUE_TYPE_STRING) { SafeStr(out, std::string("\t\t\t\t" + ii.first + " = ").c_str(), ii.second.valueTypeString); } else { fprintf(out, "\t\t\t\t%s = %s,\n", ii.first.c_str(), ii.second.GetValueAsString(false).c_str()); } } std::vector<std::string> deps = archData.GetDependencies(); if (archData.IsMap()) { FilterDep(deps, GetMapHelperContentName()); } else if (archData.IsGame()) { FilterDep(deps, GetSpringBaseContentName()); } if (!deps.empty()) { fprintf(out, "\t\t\t\tdepend = {\n"); for (unsigned d = 0; d < deps.size(); d++) { SafeStr(out, "\t\t\t\t\t", deps[d]); } fprintf(out, "\t\t\t\t},\n"); } fprintf(out, "\t\t\t},\n"); } fprintf(out, "\t\t},\n"); } fprintf(out, "\t},\n\n"); // close 'archives' fprintf(out, "\tbrokenArchives = { -- count = %u\n", unsigned(brokenArchives.size())); for (const auto& bai: brokenArchives) { const BrokenArchive& ba = bai.second; fprintf(out, "\t\t{\n"); SafeStr(out, "\t\t\tname = ", bai.first); SafeStr(out, "\t\t\tpath = ", ba.path); fprintf(out, "\t\t\tmodified = \"%u\",\n", ba.modified); SafeStr(out, "\t\t\tproblem = ", ba.problem); fprintf(out, "\t\t},\n"); } fprintf(out, "\t},\n"); // close 'brokenArchives' fprintf(out, "}\n\n"); // close 'archiveCache' fprintf(out, "return archiveCache\n"); if (fclose(out) == EOF) LOG_L(L_ERROR, "[AS::%s] failed to write to \"%s\"!", __func__, filename.c_str()); isDirty = false; }