diff --git a/src/generators.h b/src/generators.h index 6dd2cae2..34d4c1ef 100644 --- a/src/generators.h +++ b/src/generators.h @@ -25,22 +25,24 @@ #include "helpers.h" #include "metadata.h" +#include "globals.h" #include +#include -#include #include #include +#include namespace boss { - void WriteMessage(pugi::xml_node& listItem, std::string type, std::string content) { + inline void WriteMessage(pugi::xml_node& listItem, unsigned int type, std::string content) { - if (type == "say") + if (type == MESSAGE_SAY) content = "Note: " + content; - else if (type == "tag") { + else if (type == MESSAGE_TAG) { content = "Bash Tag Suggestion(s): " + content; - } else if (type == "warn") + } else if (type == MESSAGE_WARN) content = "Warning: " + content; else content = "Error: " + content; @@ -88,7 +90,7 @@ namespace boss { } - void GenerateHead(pugi::xml_document& doc) { + inline void GenerateHead(pugi::xml_document& doc) { //Add DOCTYPE node. doc.append_child(pugi::node_doctype).set_value("html"); @@ -132,7 +134,7 @@ namespace boss { node.set_value("[if IE 8]>& messages, int& warnNo, int& errorNo) { + inline void AppendMessages(pugi::xml_node& parent, const std::list& messages, int& warnNo, int& errorNo) { if (!messages.empty()) { pugi::xml_node list = parent.append_child(); list.set_name("ul"); @@ -167,20 +169,24 @@ namespace boss { pugi::xml_node li = list.append_child(); li.set_name("li"); - li.append_attribute("class").set_value(it->Type().c_str()); + + if (it->Type() == MESSAGE_SAY) + li.append_attribute("class").set_value("say"); + else if (it->Type() == MESSAGE_WARN) { + li.append_attribute("class").set_value("warn"); + ++warnNo; + } else { + li.append_attribute("class").set_value("error"); + ++errorNo; + } //Turn any urls into hyperlinks. WriteMessage(li, it->Type(), it->Content()); - - if (boost::iequals(it->Type(), "warn")) - ++warnNo; - else if (boost::iequals(it->Type(), "error")) - ++errorNo; } } } - void AppendSummary(pugi::xml_node& main, + inline void AppendSummary(pugi::xml_node& main, bool hasChanged, const std::string& masterlistVersion, bool masterlistUpdateEnabled, @@ -268,7 +274,7 @@ namespace boss { cell.text().set(IntToString(errorNo).c_str()); } - void AppendDetails(pugi::xml_node& main, const std::list& plugins, int& messageNo, int& warnNo, int& errorNo) { + inline void AppendDetails(pugi::xml_node& main, const std::list& plugins, int& messageNo, int& warnNo, int& errorNo) { pugi::xml_node details = main.append_child(); details.set_name("div"); @@ -312,7 +318,7 @@ namespace boss { content += "Bash Tags suggested for addition are " + add.substr(2) + ". "; if (!remove.empty()) content += "Bash Tags suggested for removal are " + remove.substr(2) + ". "; - messages.push_back(Message("tag", content)); //Special type just for tag suggestions. + messages.push_back(Message(MESSAGE_TAG, content)); //Special type just for tag suggestions. } AppendMessages(plugin, messages, warnNo, errorNo); @@ -322,7 +328,7 @@ namespace boss { } - void AppendMain(pugi::xml_node& body, + inline void AppendMain(pugi::xml_node& body, bool hasChanged, const std::string& masterlistVersion, bool masterlistUpdateEnabled, @@ -350,7 +356,7 @@ namespace boss { AppendSummary(main, hasChanged, masterlistVersion, masterlistUpdateEnabled, messageNo, warnNo, errorNo, messages); } - void AppendFilters(pugi::xml_node& body, int messageNo, int pluginNo) { + inline void AppendFilters(pugi::xml_node& body, int messageNo, int pluginNo) { pugi::xml_node filters = body.append_child(); filters.set_name("div"); @@ -427,7 +433,7 @@ namespace boss { label.append_child(pugi::node_pcdata).set_value((" of " + IntToString(messageNo) + " messages hidden.").c_str()); } - void AppendScripts(pugi::xml_node& body) { + inline void AppendScripts(pugi::xml_node& body) { pugi::xml_node node; @@ -438,7 +444,7 @@ namespace boss { } - void GenerateReport(const std::string& file, + inline void GenerateReport(const std::string& file, const std::list& messages, const std::list& plugins, const std::string& masterlistVersion, @@ -469,3 +475,123 @@ namespace boss { } #endif + +namespace YAML { + template + Emitter& operator << (Emitter& out, const std::set& rhs) { + out << BeginSeq; + for (typename std::set::const_iterator it=rhs.begin(), endIt=rhs.end(); it != endIt; ++it) { + out << *it; + } + out << EndSeq; + } + + inline Emitter& operator << (Emitter& out, const boss::Game& rhs) { + out << BeginMap + << Key << rhs.FolderName() << Value + << BeginMap + << Key << "name" << Value << rhs.Name() + << Key << "master" << Value << rhs.Master() + << Key << "url" << Value << rhs.URL() + << Key << "path" << Value << rhs.GamePath().string() + << Key << "registry" << Value << rhs.RegistryKey(); + + if (rhs.Id() == boss::GAME_TES4) + out << Key << Value << boss::Game(boss::GAME_TES4).FolderName(); + else if (rhs.Id() == boss::GAME_TES5) + out << Key << Value << boss::Game(boss::GAME_TES5).FolderName(); + else if (rhs.Id() == boss::GAME_FO3) + out << Key << Value << boss::Game(boss::GAME_FO3).FolderName(); + else if (rhs.Id() == boss::GAME_FONV) + out << Key << Value << boss::Game(boss::GAME_FONV).FolderName(); + + out << EndMap << EndMap; + } + + inline Emitter& operator << (Emitter& out, const boss::Message& rhs) { + out << BeginMap; + + if (rhs.Type() == boss::MESSAGE_SAY) + out << Key << "type" << Value << "say"; + else if (rhs.Type() == boss::MESSAGE_WARN) + out << Key << "type" << Value << "warn"; + else + out << Key << "type" << Value << "error"; + + out << Key << "content" << Value << rhs.Content(); + + if (rhs.Language() == boss::LANG_ENG) + out << Key << "lang" << Value << "eng"; + + if (!rhs.Condition().empty()) + out << Key << "condition" << Value << rhs.Condition(); + + out << EndMap; + } + + inline Emitter& operator << (Emitter& out, const boss::File& rhs) { + if (!rhs.IsConditional() && rhs.DisplayName().empty()) + out << rhs.Name(); + else { + out << BeginMap + << Key << "name" << Value << rhs.Name(); + + if (rhs.IsConditional()) + out << Key << "condition" << Value << rhs.Condition(); + + if (!rhs.DisplayName().empty()) + out << Key << "display" << Value << rhs.DisplayName(); + + out << EndMap; + } + } + + inline Emitter& operator << (Emitter& out, const boss::Tag& rhs) { + if (!rhs.IsConditional()) { + if (rhs.IsAddition()) + out << rhs.Name(); + else + out << '-' << rhs.Name(); + } else { + out << BeginMap; + if (rhs.IsAddition()) + out << Key << "name" << Value << rhs.Name(); + else + out << Key << "name" << Value << '-' << rhs.Name(); + + out << Key << "condition" << Value << rhs.Condition() + << EndMap; + } + } + + inline Emitter& operator << (Emitter& out, const boss::Plugin& rhs) { + //if (!rhs.HasNameOnly()) { + + out << BeginMap + << Key << "name" << Value << rhs.Name(); + + if (rhs.Priority() != 0) + out << Key << "priority" << Value << rhs.Priority(); + + if (!rhs.Enabled()) + out << Key << "enabled" << Value << rhs.Enabled(); + + if (!rhs.LoadAfter().empty()) + out << Key << "after" << Value << rhs.LoadAfter(); + + if (!rhs.Reqs().empty()) + out << Key << "req" << Value << rhs.Reqs(); + + if (!rhs.Incs().empty()) + out << Key << "inc" << Value << rhs.Incs(); + + if (!rhs.Messages().empty()) + out << Key << "msg" << Value << rhs.Messages(); + + if (!rhs.Tags().empty()) + out << Key << "tag" << Value << rhs.Tags(); + + out << EndMap; + //} + } +} diff --git a/src/gui/main.cpp b/src/gui/main.cpp index fe6c2fc7..bdac97d9 100644 --- a/src/gui/main.cpp +++ b/src/gui/main.cpp @@ -149,6 +149,14 @@ bool BossGUI::OnInit() { wxOK | wxICON_ERROR, NULL); return false; + } catch (YAML::Exception& e) { + //LOG_ERROR("Error: %s", e.getString().c_str()); + wxMessageBox( + FromUTF8(format(loc::translate("Error: Settings parsing failed. %1%")) % e.what()), + translate("BOSS: Error"), + wxOK | wxICON_ERROR, + NULL); + return false; } if (_detectedGames.empty()) { wxMessageBox( @@ -167,7 +175,7 @@ bool BossGUI::OnInit() { if (!target.empty()) { for (size_t i=0, max=_detectedGames.size(); i < max; ++i) { - if (boost::iequals(target, _detectedGames[i].FolderName())) + if (target == _detectedGames[i].FolderName()) _game = _detectedGames[i]; } if (_game == Game()) @@ -388,6 +396,11 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) { messages = mlist_messages; messages.insert(messages.end(), ulist_messages.begin(), ulist_messages.end()); + //Set language. + unsigned int lang = boss::LANG_AUTO; + if (_settings["Language"].as() == "eng") + lang = boss::LANG_ENG; + //Merge plugin list, masterlist and userlist plugin data. for (list::iterator it=plugins.begin(), endIt=plugins.end(); it != endIt; ++it) { //Check if there is already a plugin in the 'plugins' list or not. @@ -405,7 +418,7 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) { //Now that items are merged, evaluate any conditions they have. try { - it->EvalAllConditions(_game, _settings["Language"].as()); + it->EvalAllConditions(_game, lang); } catch (boss::error& e) { //LOG_ERROR("Error: %s", e.what()); wxMessageBox( @@ -423,9 +436,9 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) { list messages = it->Messages(); for (map::const_iterator jt=issues.begin(), endJt=issues.end(); jt != endJt; ++jt) { if (jt->second) - messages.push_back(boss::Message("error", "\"" + jt->first + "\" is incompatible with \"" + it->Name() + "\" and is present.")); + messages.push_back(boss::Message(boss::MESSAGE_ERROR, "\"" + jt->first + "\" is incompatible with \"" + it->Name() + "\" and is present.")); else - messages.push_back(boss::Message("error", "\"" + jt->first + "\" is required by \"" + it->Name() + "\" but is missing.")); + messages.push_back(boss::Message(boss::MESSAGE_ERROR, "\"" + jt->first + "\" is required by \"" + it->Name() + "\" but is missing.")); } if (!issues.empty()) it->Messages(messages); @@ -442,7 +455,7 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) { out << "Sorting plugins..." << endl; - //Iterate through the container. For each element, compare it against all those following it and insert those that are < it before it. After each insert, step back to the inserted element and compare for that. + //std::sort doesn't compare each plugin to every other plugin, it seems to compare plugins until no movement is necessary, because it assumes that each plugin will be comparable on all tested data, which isn't the case when dealing with masters, etc. Therefore, loop through the list and move each plugin's dependencies directly before it, then apply std::sort. list::iterator it=plugins.begin(); while (it != plugins.end()) { list::iterator jt=it; @@ -452,7 +465,7 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) { list moved; while (jt != plugins.end()) { - if (*jt < *it) { + if (it->MustLoadAfter(*jt)) { moved.push_back(*jt); jt = plugins.erase(jt); } else @@ -469,7 +482,7 @@ void Launcher::OnSortPlugins(wxCommandEvent& event) { progDia->Pulse(); } - plugins.sort(boss::flex_sort); + plugins.sort(boss::load_order_sort); end = time(NULL); out << "Time taken to sort plugins: " << (end - start) << " seconds." << endl; diff --git a/src/metadata.cpp b/src/metadata.cpp index a8ae5924..71a69411 100644 --- a/src/metadata.cpp +++ b/src/metadata.cpp @@ -51,27 +51,14 @@ namespace boss { } bool FormID::operator == (const FormID& rhs) const { - return (boost::iequals(plugin, rhs.Plugin()) && id == rhs.Id()); - } - - bool FormID::operator != (const FormID& rhs) const { - return !(*this == rhs); + return (id == rhs.Id() && boost::iequals(plugin, rhs.Plugin())); } bool FormID::operator < (const FormID& rhs) const { - return (id < rhs.Id() || plugin < rhs.Plugin()); - } - - bool FormID::operator > (const FormID& rhs) const { - return !(*this == rhs || *this < rhs); - } - - bool FormID::operator <= (const FormID& rhs) const { - return (*this == rhs || *this < rhs); - } - - bool FormID::operator >= (const FormID& rhs) const { - return !(*this < rhs); + if (id != rhs.Id()) + return id < rhs.Id(); + else + return boost::ilexicographical_compare(plugin, rhs.Plugin()); } std::string FormID::Plugin() const { @@ -138,35 +125,32 @@ namespace boss { } Message::Message() {} - - Message::Message(const std::string& t, const std::string& cont) - : type(t), ConditionalData("", cont) {} - - Message::Message(const std::string& t, const std::string& cont, - const std::string& cond, const std::string& l) - : type(t), language(l), ConditionalData(cond, cont) {} + + Message::Message(const unsigned int type, const std::string& content, + const std::string& condition, const unsigned int language) + : _type(type), _language(language), ConditionalData(condition, content) {} bool Message::operator < (const Message& rhs) const { - return (Content() < rhs.Content()); + return boost::ilexicographical_compare(Content(), rhs.Content()); } bool Message::operator == (const Message& rhs) const { - return (boost::iequals(Type(), rhs.Type()) && boost::iequals(Content(), rhs.Content())); + return (_type == rhs.Type() && boost::iequals(Content(), rhs.Content())); } - bool Message::EvalCondition(boss::Game& game, const std::string& lang) const { - if (language.empty() || boost::iequals(language, lang)) + bool Message::EvalCondition(boss::Game& game, const unsigned int lang) const { + if (_language == LANG_AUTO || _language == lang) return ConditionalData::EvalCondition(game); else return false; } - std::string Message::Type() const { - return type; + unsigned int Message::Type() const { + return _type; } - std::string Message::Language() const { - return language; + unsigned int Message::Language() const { + return _language; } std::string Message::Content() const { @@ -174,12 +158,11 @@ namespace boss { } File::File() {} - File::File(const std::string& n) : ConditionalData("", n) {} - File::File(const std::string& n, const std::string& d, const std::string& c) - : display(d), ConditionalData(c, n) {} + File::File(const std::string& name, const std::string& display, const std::string& condition) + : _display(display), ConditionalData(condition, name) {} bool File::operator < (const File& rhs) const { - return (Name() < rhs.Name()); + return boost::ilexicographical_compare(Name(), rhs.Name()); } bool File::operator == (const File& rhs) const { @@ -191,71 +174,41 @@ namespace boss { } std::string File::DisplayName() const { - return display; + return _display; } Tag::Tag() : addTag(true) {} - Tag::Tag(const string& tag) { - string data; - if (tag[0] == '-') { - addTag = false; - data = tag.substr(1); - } else { - addTag = true; - data = tag; - } - Data(data); - } - - Tag::Tag(const string& tag, const string& condition) : ConditionalData(condition) { - string data; - if (tag[0] == '-') { - addTag = false; - data = tag.substr(1); - } else { - addTag = true; - data = tag; - } - Data(data); - } + Tag::Tag(const string& tag, const bool isAddition, const string& condition) : addTag(isAddition), ConditionalData(condition, tag) {} bool Tag::operator < (const Tag& rhs) const { - return (PrefixedName() < rhs.PrefixedName()); + if (addTag != rhs.IsAddition()) + return (addTag && !rhs.IsAddition()); + else + return boost::ilexicographical_compare(Name(), rhs.Name()); } bool Tag::operator == (const Tag& rhs) const { - return boost::iequals(PrefixedName(), rhs.PrefixedName()); + return (addTag == rhs.IsAddition() && boost::iequals(Name(), rhs.Name())); } bool Tag::IsAddition() const { return addTag; } - string Tag::PrefixedName() const { - if (addTag) - return Name(); - else - return "-" + Name(); - } - std::string Tag::Name() const { return Data(); } - Plugin::Plugin() : enabled(true), priority(0), isMaster(false), isActive(false), crc(0) {} - Plugin::Plugin(const std::string& n) : name(n), enabled(true), priority(0), isMaster(false), isActive(false), crc(0) {} + Plugin::Plugin() : enabled(true), priority(0), isMaster(false) {} + Plugin::Plugin(const std::string& n) : name(n), enabled(true), priority(0), isMaster(false) {} Plugin::Plugin(boss::Game& game, const std::string& n, const bool headerOnly) : name(n), enabled(true), priority(0) { // Get data from file contents using libespm. Assumes libespm has already been initialised. boost::filesystem::path filepath = game.DataPath() / n; - espm::File file; - if (headerOnly) - file = espm::File(filepath.string(), game.espm_settings, false, true); - else - file = espm::File(filepath.string(), game.espm_settings, false, false); + espm::File file(filepath.string(), game.espm_settings, false, headerOnly); isMaster = file.isMaster(game.espm_settings); masters = file.getMasters(); @@ -312,19 +265,6 @@ namespace boss { break; } } - - //Calculate the plugin's CRC, and add it to the hashset. - boost::unordered_map::iterator it = game.crcCache.find(boost::to_lower_copy(name)); - - if (it != game.crcCache.end()) - crc = it->second; - else { - crc = GetCrc32(game.DataPath() / name); - game.crcCache.emplace(boost::to_lower_copy(name), crc); - } - - //Check if plugin is active. - isActive = game.IsActive(name); } void Plugin::Merge(const Plugin& plugin, bool ifDisabled) { @@ -463,7 +403,7 @@ namespace boss { tags = t; } - void Plugin::EvalAllConditions(boss::Game& game, const std::string& language) { + void Plugin::EvalAllConditions(boss::Game& game, const unsigned int language) { for (set::iterator it = loadAfter.begin(); it != loadAfter.end();) { if (!it->EvalCondition(game)) loadAfter.erase(it++); @@ -515,50 +455,6 @@ namespace boss { bool Plugin::operator != (const Plugin& rhs) const { return !(*this == rhs); } - - bool Plugin::operator < (const Plugin& rhs) const { - - /* If this plugin is a master and the other isn't, this plugin should load first. - * If this plugin is a master of the other plugin, this plugin should load first. - * If this plugin conflicts with the other plugin, then the plugin which contains the most records overall should load first. - */ - - if (IsMaster() && !rhs.IsMaster()) - return true; - - if (!IsMaster() && rhs.IsMaster()) - return false; - - if (rhs.MustLoadAfter(*this)) - return true; - - if (MustLoadAfter(rhs)) - return false; - - if (Priority() < rhs.Priority()) - return true; - - if (Priority() > rhs.Priority()) - return false; - - if (!OverlapFormIDs(rhs).empty() && formIDs.size() != rhs.FormIDs().size()) - return formIDs.size() > rhs.FormIDs().size(); - - //return false; - return name < rhs.Name(); - } - - bool Plugin::operator > (const Plugin& rhs) const { - return !(*this == rhs || *this < rhs); - } - - bool Plugin::operator <= (const Plugin& rhs) const { - return (*this == rhs || *this < rhs); - } - - bool Plugin::operator >= (const Plugin& rhs) const { - return !(*this < rhs); - } std::set Plugin::FormIDs() const { return formIDs; @@ -568,7 +464,17 @@ namespace boss { set otherFormIDs = plugin.FormIDs(); set overlap; - set_intersection(formIDs.begin(), formIDs.end(), otherFormIDs.begin(), otherFormIDs.end(), inserter(overlap, overlap.begin())); + /* for (set::iterator it=formIDs.begin(),endit=formIDs.end(); it != endit; ++it) { + if (otherFormIDs.find(*it) != otherFormIDs.end()) + overlap.insert(*it); + } + + for (set::iterator it=otherFormIDs.begin(),endit=otherFormIDs.end(); it != endit; ++it) { + if (formIDs.find(*it) != formIDs.end()) + overlap.insert(*it); + } +*/ + set_intersection(formIDs.begin(), formIDs.end(), otherFormIDs.begin(), otherFormIDs.end(), inserter(overlap, overlap.end())); return overlap; } @@ -585,14 +491,6 @@ namespace boss { return version; } - uint32_t Plugin::Crc() const { - return crc; - } - - bool Plugin::IsActive() const { - return isActive; - } - bool Plugin::MustLoadAfter(const Plugin& plugin) const { for (vector::const_iterator it=masters.begin(), endIt=masters.end(); it != endIt; ++it) { if (boost::iequals(*it, plugin.Name())) @@ -627,4 +525,33 @@ namespace boss { bool operator == (const File& lhs, const Plugin& rhs) { return boost::iequals(lhs.Name(), rhs.Name()); } + + bool alpha_sort(const Plugin& lhs, const Plugin& rhs) { + return boost::ilexicographical_compare(lhs.Name(), rhs.Name()); + } + + bool load_order_sort(const Plugin& lhs, const Plugin& rhs) { + if (lhs.IsMaster() && !rhs.IsMaster()) + return true; + + if (!lhs.IsMaster() && rhs.IsMaster()) + return false; + + if (rhs.MustLoadAfter(lhs)) + return true; + + if (lhs.MustLoadAfter(rhs)) + return false; + + if (lhs.Priority() < rhs.Priority()) + return true; + + if (lhs.Priority() > rhs.Priority()) + return false; + + if (!lhs.OverlapFormIDs(rhs).empty() && lhs.FormIDs().size() != rhs.FormIDs().size()) + return lhs.FormIDs().size() > rhs.FormIDs().size(); + + return boost::ilexicographical_compare(lhs.Name(), rhs.Name()); + } } diff --git a/src/metadata.h b/src/metadata.h index a454790c..cedfaa54 100644 --- a/src/metadata.h +++ b/src/metadata.h @@ -24,6 +24,7 @@ #define __BOSS_METADATA__ #include "game.h" +#include "globals.h" #include #include @@ -39,16 +40,10 @@ namespace boss { public: FormID(); FormID(const std::string& pluginName, const uint32_t objectID); + FormID(const std::vector& masters, const uint32_t formID); //The masters here also includes the plugin that they are masters of as the last element. - //The masters here also includes the plugin that they are masters of as the last element. - FormID(const std::vector& masters, const uint32_t formID); - - bool operator == (const FormID& rhs) const; - bool operator != (const FormID& rhs) const; bool operator < (const FormID& rhs) const; - bool operator > (const FormID& rhs) const; - bool operator <= (const FormID& rhs) const; - bool operator >= (const FormID& rhs) const; + bool operator == (const FormID& rhs) const; std::string Plugin() const; uint32_t Id() const; @@ -78,29 +73,27 @@ namespace boss { class Message : public ConditionalData { public: Message(); - Message(const std::string& type, const std::string& content); - Message(const std::string& type, const std::string& content, - const std::string& condition, const std::string& language); + Message(const unsigned int type, const std::string& content, + const std::string& condition = "", const unsigned int language = LANG_AUTO); bool operator < (const Message& rhs) const; bool operator == (const Message& rhs) const; - bool EvalCondition(boss::Game& game, const std::string& language) const; + bool EvalCondition(boss::Game& game, const unsigned int language) const; - std::string Type() const; - std::string Language() const; + unsigned int Type() const; + unsigned int Language() const; std::string Content() const; private: - std::string type; - std::string language; + unsigned int _type; + unsigned int _language; }; class File : public ConditionalData { public: File(); - File(const std::string& name); - File(const std::string& name, const std::string& display, - const std::string& condition); + File(const std::string& name, const std::string& display = "", + const std::string& condition = ""); bool operator < (const File& rhs) const; bool operator == (const File& rhs) const; @@ -108,21 +101,19 @@ namespace boss { std::string Name() const; std::string DisplayName() const; private: - std::string display; + std::string _display; }; class Tag : public ConditionalData { public: Tag(); - Tag(const std::string& tag); - Tag(const std::string& tag, const std::string& condition); + Tag(const std::string& tag, const bool isAddition = true, const std::string& condition = ""); bool operator < (const Tag& rhs) const; bool operator == (const Tag& rhs) const; bool IsAddition() const; std::string Name() const; - std::string PrefixedName() const; //Name with '-' in front if suggested for removal. private: bool addTag; }; @@ -149,8 +140,6 @@ namespace boss { std::vector Masters() const; bool IsMaster() const; //Checks master bit flag. std::string Version() const; - uint32_t Crc() const; - bool IsActive() const; void Name(const std::string& name); void Enabled(const bool enabled); @@ -161,7 +150,7 @@ namespace boss { void Messages(const std::list& messages); void Tags(const std::set& tags); - void EvalAllConditions(boss::Game& game, const std::string& language); + void EvalAllConditions(boss::Game& game, const unsigned int language); bool HasNameOnly() const; bool IsRegexPlugin() const; @@ -169,12 +158,6 @@ namespace boss { bool operator == (const Plugin& rhs) const; bool operator != (const Plugin& rhs) const; - //Compare load order positions. - bool operator < (const Plugin& rhs) const; - bool operator > (const Plugin& rhs) const; - bool operator <= (const Plugin& rhs) const; - bool operator >= (const Plugin& rhs) const; - //Load ordering functions. std::set OverlapFormIDs(const Plugin& plugin) const; bool MustLoadAfter(const Plugin& plugin) const; //Checks masters, reqs and loadAfter. @@ -195,11 +178,15 @@ namespace boss { std::set formIDs; std::string version; //Obtained from description field. bool isMaster; - bool isActive; - uint32_t crc; }; bool operator == (const File& lhs, const Plugin& rhs); + + bool alpha_sort(const Plugin& lhs, const Plugin& rhs); + + bool load_order_sort(const Plugin& lhs, const Plugin& rhs); + + } #endif diff --git a/src/parsers.h b/src/parsers.h index d08f0bc0..a109394e 100644 --- a/src/parsers.h +++ b/src/parsers.h @@ -32,7 +32,6 @@ #include "helpers.h" #include "error.h" -#include #include #include @@ -58,9 +57,20 @@ namespace YAML { static Node encode(const boss::Message& rhs) { Node node; node["condition"] = rhs.Condition(); - node["type"] = rhs.Type(); node["content"] = rhs.Content(); - node["lang"] = rhs.Language(); + + if (rhs.Type() == boss::MESSAGE_SAY) + node["type"] = "say"; + else if (rhs.Type() == boss::MESSAGE_WARN) + node["type"] = "warn"; + else + node["type"] = "error"; + + if (rhs.Language() == boss::LANG_AUTO) + node["lang"] = ""; + else + node["lang"] = "eng"; + return node; } @@ -68,17 +78,38 @@ namespace YAML { if(!node.IsMap()) return false; - std::string condition, type, content, language; + std::string condition, content; + unsigned int typeNo, langNo; if (node["condition"]) condition = node["condition"].as(); - if (node["type"]) - type = node["type"].as(); if (node["content"]) content = node["content"].as(); - if (node["lang"]) - language = node["lang"].as(); + + if (node["type"]) { + std::string type; + type = node["type"].as(); - rhs = boss::Message(type, content, condition, language); + if (boost::iequals(type, "say")) + typeNo = boss::MESSAGE_SAY; + else if (boost::iequals(type, "warn")) + typeNo = boss::MESSAGE_WARN; + else + typeNo = boss::MESSAGE_ERROR; + } + + + if (node["lang"]) { + std::string lang; + lang = node["lang"].as(); + + if (boost::iequals(lang, "eng")) + langNo = boss::LANG_ENG; + else + langNo = boss::LANG_AUTO; + } + + + rhs = boss::Message(typeNo, content, condition, langNo); return true; } }; @@ -114,21 +145,28 @@ namespace YAML { static Node encode(const boss::Tag& rhs) { Node node; node["condition"] = rhs.Condition(); - node["name"] = rhs.PrefixedName(); + if (rhs.IsAddition()) + node["name"] = rhs.Name(); + else + node["name"] = "-" + rhs.Name(); return node; } static bool decode(const Node& node, boss::Tag& rhs) { + std::string condition, tag; if(node.IsMap()) { - std::string condition, tag; if (node["condition"]) condition = node["condition"].as(); if (node["name"]) tag = node["name"].as(); - rhs = boss::Tag(tag, condition); - } else if (node.IsScalar()) { - rhs = boss::Tag(node.as()); - } + } else if (node.IsScalar()) + tag = node.as(); + + if (tag[0] == '-') + rhs = boss::Tag(tag.substr(1), false, condition); + else + rhs = boss::Tag(tag, true, condition); + return true; } }; @@ -197,92 +235,6 @@ namespace YAML { return true; } }; - - /////////////////// - // Emitter - /////////////////// - - template - Emitter& operator << (Emitter& out, const std::set& rhs) { - out << BeginSeq; - for (typename std::set::const_iterator it=rhs.begin(), endIt=rhs.end(); it != endIt; ++it) { - out << *it; - } - out << EndSeq; - } - - inline Emitter& operator << (Emitter& out, const boss::Message& rhs) { - out << BeginMap - << Key << "type" << Value << rhs.Type() - << Key << "content" << Value << rhs.Content(); - - if (!rhs.Language().empty()) - out << Key << "lang" << Value << rhs.Language(); - - if (!rhs.Condition().empty()) - out << Key << "condition" << Value << rhs.Condition(); - - out << EndMap; - } - - inline Emitter& operator << (Emitter& out, const boss::File& rhs) { - if (!rhs.IsConditional() && rhs.DisplayName().empty()) - out << rhs.Name(); - else { - out << BeginMap - << Key << "name" << Value << rhs.Name(); - - if (rhs.IsConditional()) - out << Key << "condition" << Value << rhs.Condition(); - - if (!rhs.DisplayName().empty()) - out << Key << "display" << Value << rhs.DisplayName(); - - out << EndMap; - } - } - - inline Emitter& operator << (Emitter& out, const boss::Tag& rhs) { - if (!rhs.IsConditional()) - out << rhs.PrefixedName(); - else { - out << BeginMap - << Key << "name" << Value << rhs.PrefixedName() - << Key << "condition" << Value << rhs.Condition() - << EndMap; - } - } - - inline Emitter& operator << (Emitter& out, const boss::Plugin& rhs) { - //if (!rhs.HasNameOnly()) { - - out << BeginMap - << Key << "name" << Value << rhs.Name(); - - if (rhs.Priority() != 0) - out << Key << "priority" << Value << rhs.Priority(); - - if (!rhs.Enabled()) - out << Key << "enabled" << Value << rhs.Enabled(); - - if (!rhs.LoadAfter().empty()) - out << Key << "after" << Value << rhs.LoadAfter(); - - if (!rhs.Reqs().empty()) - out << Key << "req" << Value << rhs.Reqs(); - - if (!rhs.Incs().empty()) - out << Key << "inc" << Value << rhs.Incs(); - - if (!rhs.Messages().empty()) - out << Key << "msg" << Value << rhs.Messages(); - - if (!rhs.Tags().empty()) - out << Key << "tag" << Value << rhs.Tags(); - - out << EndMap; - //} - } } namespace boss {