diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 790a897df8..5a74ca57af 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -184,7 +184,7 @@ namespace { std::ostream& mStream; - void operator()(std::monostate) const {} + void operator()(std::monostate /*value*/) const {} template void operator()(const T& value) const @@ -192,6 +192,19 @@ namespace mStream << ": " << value; } }; + + struct GetTypeData + { + const TypeData* operator()(std::monostate /*value*/) const { return sNoArg; } + + const TypeData* operator()(int /*value*/) const { return sIndexArg; } + + template + const TypeData* operator()(const T& /*value*/) const + { + return sIdArg; + } + }; } CSMWorld::UniversalId::UniversalId(const std::string& universalId) @@ -287,9 +300,17 @@ CSMWorld::UniversalId::UniversalId(Type type, const std::string& id) throw std::logic_error("invalid ID argument UniversalId type: " + std::to_string(type)); } -CSMWorld::UniversalId::UniversalId(Type type, const ESM::RefId& id) - : UniversalId(type, id.getRefIdString()) +CSMWorld::UniversalId::UniversalId(Type type, ESM::RefId id) + : mType(type) + , mValue(id) { + for (int i = 0; sIdArg[i].mName; ++i) + if (type == sIdArg[i].mType) + { + mClass = sIdArg[i].mClass; + return; + } + throw std::logic_error("invalid RefId argument UniversalId type: " + std::to_string(type)); } CSMWorld::UniversalId::UniversalId(Type type, int index) @@ -339,8 +360,7 @@ int CSMWorld::UniversalId::getIndex() const std::string CSMWorld::UniversalId::getTypeName() const { - const TypeData* typeData - = getArgumentType() == ArgumentType_None ? sNoArg : (getArgumentType() == ArgumentType_Id ? sIdArg : sIndexArg); + const TypeData* typeData = std::visit(GetTypeData{}, mValue); for (int i = 0; typeData[i].mName; ++i) if (typeData[i].mType == mType) @@ -362,8 +382,7 @@ std::string CSMWorld::UniversalId::toString() const std::string CSMWorld::UniversalId::getIcon() const { - const TypeData* typeData - = getArgumentType() == ArgumentType_None ? sNoArg : (getArgumentType() == ArgumentType_Id ? sIdArg : sIndexArg); + const TypeData* typeData = std::visit(GetTypeData{}, mValue); for (int i = 0; typeData[i].mName; ++i) if (typeData[i].mType == mType) diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 38404f68eb..8ade978a5c 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -33,6 +33,7 @@ namespace CSMWorld ArgumentType_None, ArgumentType_Id, ArgumentType_Index, + ArgumentType_RefId, }; /// \note A record list type must always be immediately followed by the matching @@ -152,7 +153,7 @@ namespace CSMWorld UniversalId(Type type, const std::string& id); ///< Using a type for a non-ID-argument UniversalId will throw an exception. - UniversalId(Type type, const ESM::RefId& id); + UniversalId(Type type, ESM::RefId id); UniversalId(Type type, int index); ///< Using a type for a non-index-argument UniversalId will throw an exception. @@ -188,7 +189,7 @@ namespace CSMWorld private: Class mClass; Type mType; - std::variant mValue; + std::variant mValue; friend bool operator==(const UniversalId& left, const UniversalId& right); diff --git a/apps/opencs_tests/model/world/testuniversalid.cpp b/apps/opencs_tests/model/world/testuniversalid.cpp index 93ddd6ce8f..960903c8de 100644 --- a/apps/opencs_tests/model/world/testuniversalid.cpp +++ b/apps/opencs_tests/model/world/testuniversalid.cpp @@ -73,6 +73,13 @@ namespace CSMWorld std::string mIcon; }; + std::ostream& operator<<(std::ostream& stream, const Params& value) + { + return stream << ".mType = " << value.mType << " .mClass = " << value.mClass + << " .mArgumentType = " << value.mArgumentType << " .mTypeName = " << value.mTypeName + << " .mString = " << value.mString << " .mIcon = " << value.mIcon; + } + struct CSMWorldUniversalIdValidPerTypeTest : TestWithParam { }; @@ -152,8 +159,11 @@ namespace CSMWorld UniversalId::ArgumentType_Id, "Instance", "Instance: f", ":./instance.png" }, Params{ UniversalId(UniversalId::Type_Reference, ESM::RefId::stringRefId("g")), UniversalId::Type_Reference, - UniversalId::Class_SubRecord, UniversalId::ArgumentType_Id, "Instance", "Instance: g", + UniversalId::Class_SubRecord, UniversalId::ArgumentType_RefId, "Instance", "Instance: \"g\"", ":./instance.png" }, + Params{ UniversalId(UniversalId::Type_Reference, ESM::RefId::index(ESM::REC_SKIL, 42)), + UniversalId::Type_Reference, UniversalId::Class_SubRecord, UniversalId::ArgumentType_RefId, "Instance", + "Instance: Index:SKIL:0x2a", ":./instance.png" }, }; INSTANTIATE_TEST_SUITE_P(ValidParams, CSMWorldUniversalIdValidPerTypeTest, ValuesIn(validParams));