mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Cache CRCs alongside conditions
This commit is contained in:
@@ -67,6 +67,23 @@ std::pair<bool, bool> GameCache::GetCachedCondition(
|
||||
return pair<bool, bool>(false, false);
|
||||
}
|
||||
|
||||
uint32_t GameCache::GetCachedCrc(const std::string& file) const {
|
||||
lock_guard<mutex> guard(mutex_);
|
||||
|
||||
auto it = crcs_.find(to_lower(file));
|
||||
|
||||
if (it != crcs_.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GameCache::CacheCrc(const std::string& file, uint32_t crc) {
|
||||
lock_guard<mutex> guard(mutex_);
|
||||
crcs_.insert(pair<string, uint32_t>(to_lower(file), crc));
|
||||
}
|
||||
|
||||
std::set<std::shared_ptr<const Plugin>> GameCache::GetPlugins() const {
|
||||
std::set<std::shared_ptr<const Plugin>> output;
|
||||
std::transform(
|
||||
@@ -116,6 +133,7 @@ void GameCache::ClearCachedConditions() {
|
||||
lock_guard<mutex> guard(mutex_);
|
||||
|
||||
conditions_.clear();
|
||||
crcs_.clear();
|
||||
}
|
||||
|
||||
void GameCache::ClearCachedPlugins() {
|
||||
|
||||
@@ -43,6 +43,9 @@ public:
|
||||
std::pair<bool, bool> GetCachedCondition(const std::string& condition) const;
|
||||
void CacheCondition(const std::string& condition, bool result);
|
||||
|
||||
uint32_t GetCachedCrc(const std::string& file) const;
|
||||
void CacheCrc(const std::string& file, uint32_t crc);
|
||||
|
||||
std::set<std::shared_ptr<const Plugin>> GetPlugins() const;
|
||||
std::shared_ptr<const Plugin> GetPlugin(const std::string& pluginName) const;
|
||||
void AddPlugin(const Plugin&& plugin);
|
||||
@@ -56,6 +59,7 @@ public:
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, bool> conditions_;
|
||||
std::unordered_map<std::string, uint32_t> crcs_;
|
||||
std::unordered_map<std::string, std::shared_ptr<const Plugin>> plugins_;
|
||||
std::set<boost::filesystem::path> archivePaths_;
|
||||
|
||||
|
||||
@@ -75,25 +75,7 @@ bool ConditionEvaluator::evaluate(const PluginCleaningData& cleaningData,
|
||||
if (shouldParseOnly() || pluginName.empty())
|
||||
return false;
|
||||
|
||||
// First need to get plugin's CRC.
|
||||
uint32_t crc = 0;
|
||||
|
||||
// Get the CRC from the game plugin cache if possible.
|
||||
try {
|
||||
crc = gameCache_->GetPlugin(pluginName)->GetCRC();
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
// Otherwise calculate it from the file.
|
||||
if (crc == 0) {
|
||||
if (boost::filesystem::exists(dataPath_ / pluginName)) {
|
||||
crc = GetCrc32(dataPath_ / pluginName);
|
||||
} else if (boost::filesystem::exists(dataPath_ / (pluginName + ".ghost"))) {
|
||||
crc = GetCrc32(dataPath_ / (pluginName + ".ghost"));
|
||||
}
|
||||
}
|
||||
|
||||
return cleaningData.GetCRC() == crc;
|
||||
return cleaningData.GetCRC() == getCrc(pluginName);
|
||||
}
|
||||
|
||||
PluginMetadata ConditionEvaluator::evaluateAll(
|
||||
@@ -256,27 +238,7 @@ bool ConditionEvaluator::checksumMatches(const std::string& filePath,
|
||||
if (shouldParseOnly())
|
||||
return false;
|
||||
|
||||
uint32_t realChecksum = 0;
|
||||
if (filePath == "LOOT")
|
||||
realChecksum = GetCrc32(boost::filesystem::absolute("LOOT.exe"));
|
||||
else {
|
||||
// CRC could be for a plugin or a file.
|
||||
// Get the CRC from the game plugin cache if possible.
|
||||
try {
|
||||
realChecksum = gameCache_->GetPlugin(filePath)->GetCRC();
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
if (realChecksum == 0) {
|
||||
if (boost::filesystem::exists(dataPath_ / filePath))
|
||||
realChecksum = GetCrc32(dataPath_ / filePath);
|
||||
else if (hasPluginFileExtension(filePath, gameType_) &&
|
||||
boost::filesystem::exists(dataPath_ / (filePath + ".ghost")))
|
||||
realChecksum = GetCrc32(dataPath_ / (filePath + ".ghost"));
|
||||
}
|
||||
}
|
||||
|
||||
return checksum == realChecksum;
|
||||
return checksum == getCrc(filePath);
|
||||
}
|
||||
|
||||
bool ConditionEvaluator::compareVersions(const std::string& filePath,
|
||||
@@ -468,4 +430,41 @@ Version ConditionEvaluator::getVersion(const std::string& filePath) const {
|
||||
bool ConditionEvaluator::shouldParseOnly() const {
|
||||
return gameCache_ == nullptr || loadOrderHandler_ == nullptr;
|
||||
}
|
||||
|
||||
uint32_t ConditionEvaluator::getCrc(const std::string & file) const {
|
||||
uint32_t crc = gameCache_->GetCachedCrc(file);
|
||||
|
||||
if (crc != 0) {
|
||||
return crc;
|
||||
}
|
||||
|
||||
if (file == "LOOT") {
|
||||
crc = GetCrc32(boost::filesystem::absolute("LOOT.exe"));
|
||||
gameCache_->CacheCrc(file, crc);
|
||||
return crc;
|
||||
}
|
||||
|
||||
// Get the CRC from the game plugin cache if possible.
|
||||
try {
|
||||
crc = gameCache_->GetPlugin(file)->GetCRC();
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
// Otherwise calculate it from the file.
|
||||
if (crc == 0) {
|
||||
if (boost::filesystem::exists(dataPath_ / file)) {
|
||||
crc = GetCrc32(dataPath_ / file);
|
||||
}
|
||||
else if (hasPluginFileExtension(file, gameType_) &&
|
||||
boost::filesystem::exists(dataPath_ / (file + ".ghost"))) {
|
||||
crc = GetCrc32(dataPath_ / (file + ".ghost"));
|
||||
}
|
||||
}
|
||||
|
||||
if (crc != 0) {
|
||||
gameCache_->CacheCrc(file, crc);
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,6 +92,8 @@ private:
|
||||
|
||||
bool shouldParseOnly() const;
|
||||
|
||||
uint32_t getCrc(const std::string& file) const;
|
||||
|
||||
const GameType gameType_;
|
||||
const boost::filesystem::path dataPath_;
|
||||
const std::shared_ptr<GameCache> gameCache_;
|
||||
|
||||
@@ -70,6 +70,15 @@ TEST_P(GameCacheTest, gettingANonCachedConditionShouldReturnAFalseFalsePair) {
|
||||
EXPECT_EQ(std::make_pair(false, false), cache_.GetCachedCondition(condition));
|
||||
}
|
||||
|
||||
TEST_P(GameCacheTest, gettingACachedCrcShouldReturnTheValue) {
|
||||
cache_.CacheCrc(boost::locale::to_upper(blankEsm), 5);
|
||||
EXPECT_EQ(5, cache_.GetCachedCrc(blankEsm));
|
||||
}
|
||||
|
||||
TEST_P(GameCacheTest, gettingAnUncachedCrcShouldReturnZero) {
|
||||
EXPECT_EQ(0, cache_.GetCachedCrc(blankEsm));
|
||||
}
|
||||
|
||||
TEST_P(GameCacheTest, addingAPluginThatDoesNotExistShouldSucceed) {
|
||||
cache_.AddPlugin(Plugin(game_.Type(),
|
||||
game_.DataPath(),
|
||||
@@ -159,13 +168,15 @@ TEST_P(GameCacheTest,
|
||||
EXPECT_NO_THROW(cache_.ClearCachedConditions());
|
||||
}
|
||||
|
||||
TEST_P(GameCacheTest, clearingCachedConditionsShouldClearAnyCachedConditions) {
|
||||
TEST_P(GameCacheTest, clearingCachedConditionsShouldClearAnyCachedConditionsAndCrcs) {
|
||||
EXPECT_NO_THROW(cache_.CacheCondition(condition, true));
|
||||
cache_.CacheCrc(blankEsm, 5);
|
||||
|
||||
EXPECT_NO_THROW(cache_.ClearCachedConditions());
|
||||
|
||||
EXPECT_EQ(std::make_pair(false, false),
|
||||
cache_.GetCachedCondition(conditionLowercase));
|
||||
EXPECT_EQ(0, cache_.GetCachedCrc(blankEsm));
|
||||
}
|
||||
|
||||
TEST_P(GameCacheTest, clearingCachedPluginsShouldNotThrowIfNoPluginsAreCached) {
|
||||
|
||||
Reference in New Issue
Block a user