From c259553833769a9fcfbe146fb74cd545446a9df4 Mon Sep 17 00:00:00 2001 From: WrinklyNinja Date: Mon, 25 Aug 2014 23:08:29 +0100 Subject: [PATCH] Metadata plugin lists now stored as hashsets. Closes #249. --- src/backend/game.cpp | 18 +++---------- src/backend/game.h | 4 +-- src/backend/generators.h | 12 +++++++++ src/backend/git.cpp | 6 +++-- src/backend/metadata.cpp | 6 +++-- src/backend/metadata.h | 2 +- src/backend/parsers.h | 23 +++++++++++++++++ src/gui/handler.cpp | 55 ++++++++++++++++++++++++++++++---------- 8 files changed, 91 insertions(+), 35 deletions(-) diff --git a/src/backend/game.cpp b/src/backend/game.cpp index f1aeb8f1..291ea7fe 100644 --- a/src/backend/game.cpp +++ b/src/backend/game.cpp @@ -108,7 +108,7 @@ namespace loot { in.close(); if (metadataList["plugins"]) - plugins = metadataList["plugins"].as< list >(); + plugins = metadataList["plugins"].as< unordered_set >(); if (metadataList["globals"]) messages = metadataList["globals"].as< list >(); @@ -141,7 +141,7 @@ namespace loot { } else { for (const auto& rhsPlugin : rhs.plugins) { - const auto it = std::find(this->plugins.begin(), this->plugins.end(), rhsPlugin); + const auto it = this->plugins.find(rhsPlugin); if (it == this->plugins.end()) { BOOST_LOG_TRIVIAL(info) << "Metadata added for plugin: " << it->Name(); @@ -166,15 +166,6 @@ namespace loot { return true; } - Plugin MetadataList::FindPlugin(const std::string& name) const { - auto it = std::find(plugins.begin(), plugins.end(), Plugin(name)); - - if (it != plugins.end()) - return *it; - else - return Plugin(name); - } - // Masterlist member functions //---------------------------- @@ -752,11 +743,10 @@ namespace loot { BOOST_LOG_TRIVIAL(info) << "Merging masterlist, userlist into plugin list, evaluating conditions and checking for install validity."; for (const auto &plugin : this->plugins) { vertex_t v = boost::add_vertex(plugin.second, graph); - list::iterator pos; BOOST_LOG_TRIVIAL(trace) << "Merging for plugin \"" << graph[v].Name() << "\""; //Check if there is a plugin entry in the masterlist. This will also find matching regex entries. - pos = std::find(this->masterlist.plugins.begin(), this->masterlist.plugins.end(), graph[v]); + auto pos = this->masterlist.plugins.find(graph[v]); if (pos != this->masterlist.plugins.end()) { BOOST_LOG_TRIVIAL(trace) << "Merging masterlist data down to plugin list data."; @@ -764,7 +754,7 @@ namespace loot { } //Check if there is a plugin entry in the userlist. This will also find matching regex entries. - pos = std::find(this->userlist.plugins.begin(), this->userlist.plugins.end(), graph[v]); + pos = this->userlist.plugins.find(graph[v]); if (pos != this->userlist.plugins.end() && pos->Enabled()) { BOOST_LOG_TRIVIAL(trace) << "Merging userlist data down to plugin list data."; diff --git a/src/backend/game.h b/src/backend/game.h index 69b2cfc7..8d745b77 100644 --- a/src/backend/game.h +++ b/src/backend/game.h @@ -61,9 +61,7 @@ namespace loot { bool operator == (const MetadataList& rhs) const; //Compares content. - Plugin FindPlugin(const std::string& name) const; - - std::list plugins; + std::unordered_set plugins; std::list messages; }; diff --git a/src/backend/generators.h b/src/backend/generators.h index 98234a10..55b60af4 100644 --- a/src/backend/generators.h +++ b/src/backend/generators.h @@ -30,6 +30,7 @@ #include #include +#include #include namespace YAML { @@ -44,6 +45,17 @@ namespace YAML { return out; } + template + Emitter& operator << (Emitter& out, const std::unordered_set& rhs) { + out << BeginSeq; + for (const auto &element : rhs) { + out << element; + } + out << EndSeq; + + return out; + } + Emitter& operator << (Emitter& out, const loot::PluginDirtyInfo& rhs); Emitter& operator << (Emitter& out, const loot::Game& rhs); diff --git a/src/backend/git.cpp b/src/backend/git.cpp index f9b8e002..48e2396e 100644 --- a/src/backend/git.cpp +++ b/src/backend/git.cpp @@ -431,9 +431,11 @@ namespace loot { try { this->MetadataList::Load(game.MasterlistPath()); - for (auto &plugin: plugins) { - plugin.EvalAllConditions(game, language); + unordered_set tempSet; + for (auto &plugin : plugins) { + tempSet.insert(Plugin(plugin).EvalAllConditions(game, language)); } + plugins = tempSet; for (auto &message: messages) { message.EvalCondition(game, language); diff --git a/src/backend/metadata.cpp b/src/backend/metadata.cpp index e2e46333..fda62353 100644 --- a/src/backend/metadata.cpp +++ b/src/backend/metadata.cpp @@ -573,7 +573,7 @@ namespace loot { _dirtyInfo = dirtyInfo; } - void Plugin::EvalAllConditions(loot::Game& game, const unsigned int language) { + Plugin& Plugin::EvalAllConditions(loot::Game& game, const unsigned int language) { for (auto it = loadAfter.begin(); it != loadAfter.end();) { if (!it->EvalCondition(game)) loadAfter.erase(it++); @@ -629,6 +629,8 @@ namespace loot { else ++it; } + + return *this; } bool Plugin::HasNameOnly() const { @@ -798,7 +800,7 @@ namespace loot { size_t plugin_hash::operator () (const Plugin& p) const { size_t seed = 0; - boost::hash_combine(seed, p.Name()); + boost::hash_combine(seed, boost::locale::to_lower(p.Name())); return seed; } diff --git a/src/backend/metadata.h b/src/backend/metadata.h index b897dcae..48aab97b 100644 --- a/src/backend/metadata.h +++ b/src/backend/metadata.h @@ -202,7 +202,7 @@ namespace loot { void Tags(const std::set& tags); void DirtyInfo(const std::set& info); - void EvalAllConditions(loot::Game& game, const unsigned int language); + Plugin& EvalAllConditions(loot::Game& game, const unsigned int language); bool HasNameOnly() const; bool IsRegexPlugin() const; bool LoadsBSA(const Game& game) const; diff --git a/src/backend/parsers.h b/src/backend/parsers.h index 33469128..bd93daed 100644 --- a/src/backend/parsers.h +++ b/src/backend/parsers.h @@ -315,6 +315,29 @@ namespace YAML { } }; + template + struct convert< std::unordered_set > { + static Node encode(const std::unordered_set& rhs) { + Node node; + for (const auto &element : rhs) { + node.push_back(element); + } + return node; + } + + static bool decode(const Node& node, std::unordered_set& rhs) { + if (!node.IsSequence()) + return false; + + rhs.clear(); + for (const auto &element : node) { + rhs.insert(element.as()); + } + return true; + + } + }; + template<> struct convert { static Node encode(const loot::Plugin& rhs) { diff --git a/src/gui/handler.cpp b/src/gui/handler.cpp index 35a0eb76..a4a12315 100644 --- a/src/gui/handler.cpp +++ b/src/gui/handler.cpp @@ -381,8 +381,15 @@ namespace loot { BOOST_LOG_TRIVIAL(debug) << "Copying metadata for plugin " << pluginName; // Get metadata from masterlist and userlist. - Plugin plugin = g_app_state.CurrentGame().masterlist.FindPlugin(pluginName); - plugin.MergeMetadata(g_app_state.CurrentGame().userlist.FindPlugin(pluginName)); + Plugin plugin; + auto it = g_app_state.CurrentGame().masterlist.plugins.find(pluginName); + if (it != g_app_state.CurrentGame().masterlist.plugins.end()) { + plugin = *it; + } + it = g_app_state.CurrentGame().userlist.plugins.find(pluginName); + if (it != g_app_state.CurrentGame().userlist.plugins.end()) { + plugin.MergeMetadata(*it); + } // Generate text representation. string text; @@ -405,7 +412,7 @@ namespace loot { std::string Handler::ClearPluginMetadata(const std::string& pluginName) { BOOST_LOG_TRIVIAL(debug) << "Clearing user metadata for plugin " << pluginName; - auto ulistPluginIt = find(g_app_state.CurrentGame().userlist.plugins.begin(), g_app_state.CurrentGame().userlist.plugins.end(), Plugin(pluginName)); + auto ulistPluginIt = g_app_state.CurrentGame().userlist.plugins.find(Plugin(pluginName)); if (ulistPluginIt != g_app_state.CurrentGame().userlist.plugins.end()) { g_app_state.CurrentGame().userlist.plugins.erase(ulistPluginIt); @@ -439,7 +446,7 @@ namespace loot { Plugin newUserlistEntry(pluginMetadata["name"].as()); // Find existing userlist entry. - auto ulistPluginIt = find(g_app_state.CurrentGame().userlist.plugins.begin(), g_app_state.CurrentGame().userlist.plugins.end(), newUserlistEntry); + auto ulistPluginIt = g_app_state.CurrentGame().userlist.plugins.find(newUserlistEntry); // First sort out the priority value. This is only given if it was changed. BOOST_LOG_TRIVIAL(trace) << "Calculating userlist metadata priority value from Javascript variables."; @@ -491,12 +498,15 @@ namespace loot { BOOST_LOG_TRIVIAL(trace) << "Replacing existing userlist entry with new metadata."; if (newUserlistEntry.HasNameOnly()) g_app_state.CurrentGame().userlist.plugins.erase(ulistPluginIt); - else - *ulistPluginIt = newUserlistEntry; + else { + // Set members are static, so just erase and add the new data. + g_app_state.CurrentGame().userlist.plugins.erase(ulistPluginIt); + g_app_state.CurrentGame().userlist.plugins.insert(newUserlistEntry); + } } else { BOOST_LOG_TRIVIAL(trace) << "Adding new metadata to new userlist entry."; - g_app_state.CurrentGame().userlist.plugins.push_back(newUserlistEntry); + g_app_state.CurrentGame().userlist.plugins.insert(newUserlistEntry); } // Now rederive the derived metadata. @@ -641,11 +651,17 @@ namespace loot { // description as part of it. BOOST_LOG_TRIVIAL(trace) << "Getting masterlist metadata for: " << plugin.Name(); Plugin mlistPlugin(plugin); - mlistPlugin.MergeMetadata(g_app_state.CurrentGame().masterlist.FindPlugin(plugin.Name())); - + auto it = g_app_state.CurrentGame().masterlist.plugins.find(plugin.Name()); + if (it != g_app_state.CurrentGame().masterlist.plugins.end()) { + mlistPlugin.MergeMetadata(*it); + } // Now do the same again for any userlist data. BOOST_LOG_TRIVIAL(trace) << "Getting userlist metadata for: " << plugin.Name(); - Plugin ulistPlugin(g_app_state.CurrentGame().userlist.FindPlugin(plugin.Name())); + Plugin ulistPlugin; + it = g_app_state.CurrentGame().userlist.plugins.find(plugin.Name()); + if (it != g_app_state.CurrentGame().userlist.plugins.end()) { + ulistPlugin = *it; + } pluginNode["__type"] = "Plugin"; // For conversion back into a JS typed object. pluginNode["name"] = plugin.Name(); @@ -762,7 +778,10 @@ namespace loot { for (const auto& pluginPair : g_app_state.CurrentGame().plugins) { Plugin mlistPlugin(pluginPair.second); - mlistPlugin.MergeMetadata(g_app_state.CurrentGame().masterlist.FindPlugin(pluginPair.second.Name())); + auto it = g_app_state.CurrentGame().masterlist.plugins.find(pluginPair.second); + if (it != g_app_state.CurrentGame().masterlist.plugins.end()) { + mlistPlugin.MergeMetadata(*it); + } YAML::Node pluginNode; if (!mlistPlugin.HasNameOnly()) { @@ -916,8 +935,18 @@ namespace loot { auto pluginIt = g_app_state.CurrentGame().plugins.find(boost::locale::to_lower(pluginName)); if (pluginIt != g_app_state.CurrentGame().plugins.end()) { - const Plugin master = g_app_state.CurrentGame().masterlist.FindPlugin(pluginIt->second.Name()); - const Plugin user = g_app_state.CurrentGame().userlist.FindPlugin(pluginIt->second.Name()); + Plugin master; + Plugin user; + + auto it = g_app_state.CurrentGame().masterlist.plugins.find(pluginIt->second.Name()); + if (it != g_app_state.CurrentGame().masterlist.plugins.end()) { + master = *it; + } + + it = g_app_state.CurrentGame().userlist.plugins.find(pluginIt->second.Name()); + if (it != g_app_state.CurrentGame().userlist.plugins.end()) { + user = *it; + } return this->GenerateDerivedMetadata(pluginIt->second, master, user); }