diff --git a/src/api/helpers/crc.cpp b/src/api/helpers/crc.cpp index d58037a2..59f8eb9e 100644 --- a/src/api/helpers/crc.cpp +++ b/src/api/helpers/crc.cpp @@ -25,6 +25,7 @@ #include "api/helpers/crc.h" #include +#include #include #include "api/helpers/logging.h" @@ -81,4 +82,8 @@ uint32_t GetCrc32(const std::filesystem::path& filename) { "\" for CRC calulation: " + e.what()); } } + +std::string CrcToString(uint32_t crc) { + return (boost::format("%08X") % crc).str(); +} } diff --git a/src/api/helpers/crc.h b/src/api/helpers/crc.h index 507f72f0..156f33d1 100644 --- a/src/api/helpers/crc.h +++ b/src/api/helpers/crc.h @@ -30,6 +30,8 @@ namespace loot { uint32_t GetCrc32(const std::filesystem::path& filename); + +std::string CrcToString(uint32_t crc); } #endif diff --git a/src/api/metadata/condition_evaluator.cpp b/src/api/metadata/condition_evaluator.cpp index 000d1a45..17e04616 100644 --- a/src/api/metadata/condition_evaluator.cpp +++ b/src/api/metadata/condition_evaluator.cpp @@ -82,12 +82,6 @@ int mapGameType(GameType gameType) { } } -std::string IntToHexString(const uint32_t value) { - std::stringstream stream; - stream << std::hex << value; - return stream.str(); -} - ConditionEvaluator::ConditionEvaluator(const GameType gameType, const std::filesystem::path& dataPath) : lciState_(std::unique_ptr( @@ -256,7 +250,7 @@ bool ConditionEvaluator::Evaluate(const PluginCleaningData& cleaningData, return false; return Evaluate("checksum(\"" + pluginName + "\", " + - IntToHexString(cleaningData.GetCRC()) + ")"); + CrcToString(cleaningData.GetCRC()) + ")"); } void ParseCondition(const std::string& condition) { diff --git a/src/api/metadata/yaml/file.h b/src/api/metadata/yaml/file.h index d0b979bb..85673e5b 100644 --- a/src/api/metadata/yaml/file.h +++ b/src/api/metadata/yaml/file.h @@ -35,6 +35,13 @@ #include "api/metadata/yaml/message_content.h" #include "loot/metadata/file.h" +namespace loot { +inline bool emitAsScalar(const File& file) { + return !file.IsConditional() && file.GetDetail().empty() && + file.GetDisplayName().empty(); +} +} + namespace YAML { template<> struct convert { @@ -116,10 +123,9 @@ struct convert { }; inline Emitter& operator<<(Emitter& out, const loot::File& rhs) { - if (!rhs.IsConditional() && rhs.GetDetail().empty() && - rhs.GetDisplayName().empty()) + if (loot::emitAsScalar(rhs)) { out << YAML::SingleQuoted << std::string(rhs.GetName()); - else { + } else { out << BeginMap << Key << "name" << Value << YAML::SingleQuoted << std::string(rhs.GetName()); diff --git a/src/api/metadata/yaml/location.h b/src/api/metadata/yaml/location.h index 9409f39a..ede695f3 100644 --- a/src/api/metadata/yaml/location.h +++ b/src/api/metadata/yaml/location.h @@ -33,6 +33,12 @@ #include "loot/metadata/location.h" +namespace loot { +inline bool emitAsScalar(const Location& location) { + return location.GetName().empty(); +} +} + namespace YAML { template<> struct convert { @@ -74,9 +80,9 @@ struct convert { }; inline Emitter& operator<<(Emitter& out, const loot::Location& rhs) { - if (rhs.GetName().empty()) + if (emitAsScalar(rhs)) { out << YAML::SingleQuoted << rhs.GetURL(); - else { + } else { out << BeginMap << Key << "link" << Value << YAML::SingleQuoted << rhs.GetURL() << Key << "name" << Value << YAML::SingleQuoted << rhs.GetName() << EndMap; diff --git a/src/api/metadata/yaml/plugin_cleaning_data.h b/src/api/metadata/yaml/plugin_cleaning_data.h index 379e2386..7e2bb391 100644 --- a/src/api/metadata/yaml/plugin_cleaning_data.h +++ b/src/api/metadata/yaml/plugin_cleaning_data.h @@ -32,6 +32,7 @@ #include #include +#include "api/helpers/crc.h" #include "loot/metadata/plugin_cleaning_data.h" namespace YAML { @@ -109,8 +110,9 @@ struct convert { }; inline Emitter& operator<<(Emitter& out, const loot::PluginCleaningData& rhs) { - out << BeginMap << Key << "crc" << Value << Hex << rhs.GetCRC() << Dec << Key - << "util" << Value << YAML::SingleQuoted << rhs.GetCleaningUtility(); + out << BeginMap << Key << "crc" << Value + << "0x" + loot::CrcToString(rhs.GetCRC()) << Key << "util" << Value + << YAML::SingleQuoted << rhs.GetCleaningUtility(); if (!rhs.GetDetail().empty()) { if (rhs.GetDetail().size() == 1) diff --git a/src/api/metadata/yaml/plugin_metadata.h b/src/api/metadata/yaml/plugin_metadata.h index 3902f286..71fe6b33 100644 --- a/src/api/metadata/yaml/plugin_metadata.h +++ b/src/api/metadata/yaml/plugin_metadata.h @@ -44,6 +44,17 @@ #include "api/metadata/yaml/tag.h" #include "loot/metadata/plugin_metadata.h" +namespace loot { +template +inline ::YAML::EMITTER_MANIP getNodeStyle(const std::vector& objects) { + if (objects.size() == 1 && emitAsScalar(objects.at(0))) { + return YAML::Flow; + } + + return YAML::Block; +} +} + namespace YAML { template<> struct convert { @@ -126,24 +137,39 @@ inline Emitter& operator<<(Emitter& out, const loot::PluginMetadata& rhs) { out << BeginMap << Key << "name" << Value << YAML::SingleQuoted << rhs.GetName(); - if (rhs.GetGroup()) + const auto locations = rhs.GetLocations(); + if (!locations.empty()) { + out << Key << "url" << Value << loot::getNodeStyle(locations) + << locations; + } + + if (rhs.GetGroup()) { out << Key << "group" << Value << YAML::SingleQuoted << rhs.GetGroup().value(); + } - if (!rhs.GetLoadAfterFiles().empty()) - out << Key << "after" << Value << rhs.GetLoadAfterFiles(); + const auto after = rhs.GetLoadAfterFiles(); + if (!after.empty()) { + out << Key << "after" << Value << loot::getNodeStyle(after) << after; + } - if (!rhs.GetRequirements().empty()) - out << Key << "req" << Value << rhs.GetRequirements(); + const auto req = rhs.GetRequirements(); + if (!req.empty()) { + out << Key << "req" << Value << loot::getNodeStyle(req) << req; + } - if (!rhs.GetIncompatibilities().empty()) - out << Key << "inc" << Value << rhs.GetIncompatibilities(); + const auto inc = rhs.GetIncompatibilities(); + if (!inc.empty()) { + out << Key << "inc" << Value << loot::getNodeStyle(inc) << inc; + } if (!rhs.GetMessages().empty()) out << Key << "msg" << Value << rhs.GetMessages(); - if (!rhs.GetTags().empty()) - out << Key << "tag" << Value << rhs.GetTags(); + const auto tags = rhs.GetTags(); + if (!tags.empty()) { + out << Key << "tag" << Value << loot::getNodeStyle(tags) << tags; + } if (!rhs.GetDirtyInfo().empty()) out << Key << "dirty" << Value << rhs.GetDirtyInfo(); @@ -151,9 +177,6 @@ inline Emitter& operator<<(Emitter& out, const loot::PluginMetadata& rhs) { if (!rhs.GetCleanInfo().empty()) out << Key << "clean" << Value << rhs.GetCleanInfo(); - if (!rhs.GetLocations().empty()) - out << Key << "url" << Value << rhs.GetLocations(); - out << EndMap; } diff --git a/src/api/metadata/yaml/tag.h b/src/api/metadata/yaml/tag.h index ae59fcc8..72b3084c 100644 --- a/src/api/metadata/yaml/tag.h +++ b/src/api/metadata/yaml/tag.h @@ -33,6 +33,10 @@ #include "api/metadata/condition_evaluator.h" #include "loot/metadata/tag.h" +namespace loot { +inline bool emitAsScalar(const Tag& tag) { return !tag.IsConditional(); } +} + namespace YAML { template<> struct convert { @@ -84,7 +88,7 @@ struct convert { }; inline Emitter& operator<<(Emitter& out, const loot::Tag& rhs) { - if (!rhs.IsConditional()) { + if (emitAsScalar(rhs)) { if (rhs.IsAddition()) out << rhs.GetName(); else diff --git a/src/tests/api/interface/database_interface_test.h b/src/tests/api/interface/database_interface_test.h index f567a416..99426c7e 100644 --- a/src/tests/api/interface/database_interface_test.h +++ b/src/tests/api/interface/database_interface_test.h @@ -50,7 +50,7 @@ protected: expectedContent << "plugins:" << endl << " - name: '" << blankDifferentEsm << "'" << endl << " dirty:" << endl - << " - crc: 0x7d22f9df" << endl + << " - crc: 0x7D22F9DF" << endl << " util: 'TES4Edit'" << endl << " udr: 4" << endl << " - name: '" << blankEsm << "'" << endl diff --git a/src/tests/api/internals/metadata/plugin_metadata_test.h b/src/tests/api/internals/metadata/plugin_metadata_test.h index 88f1fdf5..efd5e1b3 100644 --- a/src/tests/api/internals/metadata/plugin_metadata_test.h +++ b/src/tests/api/internals/metadata/plugin_metadata_test.h @@ -394,8 +394,7 @@ TEST_P(PluginMetadataTest, EXPECT_EQ( "name: 'Blank.esm'\n" - "after:\n" - " - 'Blank.esm'", + "after: ['Blank.esm']", plugin.AsYaml()); } @@ -418,8 +417,7 @@ TEST_P(PluginMetadataTest, EXPECT_STREQ( "name: 'Blank.esm'\n" - "after:\n" - " - 'Blank.esm'", + "after: ['Blank.esm']", emitter.c_str()); } @@ -447,8 +445,7 @@ TEST_P(PluginMetadataTest, EXPECT_STREQ( "name: 'Blank.esp'\n" - "after:\n" - " - 'Blank.esm'", + "after: ['Blank.esm']", emitter.c_str()); } @@ -462,8 +459,7 @@ TEST_P(PluginMetadataTest, EXPECT_STREQ( "name: 'Blank.esp'\n" - "req:\n" - " - 'Blank.esm'", + "req: ['Blank.esm']", emitter.c_str()); } @@ -477,8 +473,7 @@ TEST_P(PluginMetadataTest, EXPECT_STREQ( "name: 'Blank.esp'\n" - "inc:\n" - " - 'Blank.esm'", + "inc: ['Blank.esm']", emitter.c_str()); } @@ -507,8 +502,7 @@ TEST_P(PluginMetadataTest, emittingAsYamlShouldOutputAPluginWithTagsCorrectly) { EXPECT_STREQ( "name: 'Blank.esp'\n" - "tag:\n" - " - Relev", + "tag: [Relev]", emitter.c_str()); } @@ -523,7 +517,7 @@ TEST_P(PluginMetadataTest, EXPECT_STREQ( "name: 'Blank.esp'\n" "dirty:\n" - " - crc: 0x5\n" + " - crc: 0x00000005\n" " util: 'utility'\n" " detail: 'info'\n" " udr: 1\n" @@ -542,7 +536,7 @@ TEST_P(PluginMetadataTest, EXPECT_STREQ( "name: 'Blank.esp'\n" "clean:\n" - " - crc: 0x5\n" + " - crc: 0x00000005\n" " util: 'utility'", emitter.c_str()); } @@ -557,8 +551,7 @@ TEST_P(PluginMetadataTest, EXPECT_STREQ( "name: 'Blank.esp'\n" - "url:\n" - " - 'http://www.example.com'", + "url: ['http://www.example.com']", emitter.c_str()); }