Implement UniversalId with std::variant

simplify_debugging
elsid 2 years ago
parent f2a3462e59
commit 4cd5efc6ee
No known key found for this signature in database
GPG Key ID: 4DE04C198CBA7625

@ -5,6 +5,7 @@
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
#include <tuple>
#include <vector> #include <vector>
namespace namespace
@ -178,10 +179,23 @@ namespace
// end marker // end marker
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 },
}; };
struct WriteToStream
{
std::ostream& mStream;
void operator()(std::monostate) const {}
template <class T>
void operator()(const T& value) const
{
mStream << ": " << value;
}
};
} }
CSMWorld::UniversalId::UniversalId(const std::string& universalId) CSMWorld::UniversalId::UniversalId(const std::string& universalId)
: mIndex(0) : mValue(std::monostate{})
{ {
std::string::size_type index = universalId.find(':'); std::string::size_type index = universalId.find(':');
@ -192,24 +206,26 @@ CSMWorld::UniversalId::UniversalId(const std::string& universalId)
for (int i = 0; sIdArg[i].mName; ++i) for (int i = 0; sIdArg[i].mName; ++i)
if (type == sIdArg[i].mName) if (type == sIdArg[i].mName)
{ {
mArgumentType = ArgumentType_Id;
mType = sIdArg[i].mType; mType = sIdArg[i].mType;
mClass = sIdArg[i].mClass; mClass = sIdArg[i].mClass;
mId = universalId.substr(index + 2); mValue = universalId.substr(index + 2);
return; return;
} }
for (int i = 0; sIndexArg[i].mName; ++i) for (int i = 0; sIndexArg[i].mName; ++i)
if (type == sIndexArg[i].mName) if (type == sIndexArg[i].mName)
{ {
mArgumentType = ArgumentType_Index;
mType = sIndexArg[i].mType; mType = sIndexArg[i].mType;
mClass = sIndexArg[i].mClass; mClass = sIndexArg[i].mClass;
std::istringstream stream(universalId.substr(index + 2)); std::istringstream stream(universalId.substr(index + 2));
if (stream >> mIndex) int index = 0;
if (stream >> index)
{
mValue = index;
return; return;
}
break; break;
} }
@ -219,7 +235,6 @@ CSMWorld::UniversalId::UniversalId(const std::string& universalId)
for (int i = 0; sNoArg[i].mName; ++i) for (int i = 0; sNoArg[i].mName; ++i)
if (universalId == sNoArg[i].mName) if (universalId == sNoArg[i].mName)
{ {
mArgumentType = ArgumentType_None;
mType = sNoArg[i].mType; mType = sNoArg[i].mType;
mClass = sNoArg[i].mClass; mClass = sNoArg[i].mClass;
return; return;
@ -230,9 +245,8 @@ CSMWorld::UniversalId::UniversalId(const std::string& universalId)
} }
CSMWorld::UniversalId::UniversalId(Type type) CSMWorld::UniversalId::UniversalId(Type type)
: mArgumentType(ArgumentType_None) : mType(type)
, mType(type) , mValue(std::monostate{})
, mIndex(0)
{ {
for (int i = 0; sNoArg[i].mName; ++i) for (int i = 0; sNoArg[i].mName; ++i)
if (type == sNoArg[i].mType) if (type == sNoArg[i].mType)
@ -244,7 +258,7 @@ CSMWorld::UniversalId::UniversalId(Type type)
for (int i = 0; sIdArg[i].mName; ++i) for (int i = 0; sIdArg[i].mName; ++i)
if (type == sIdArg[i].mType) if (type == sIdArg[i].mType)
{ {
mArgumentType = ArgumentType_Id; mValue = std::string();
mClass = sIdArg[i].mClass; mClass = sIdArg[i].mClass;
return; return;
} }
@ -252,7 +266,7 @@ CSMWorld::UniversalId::UniversalId(Type type)
for (int i = 0; sIndexArg[i].mName; ++i) for (int i = 0; sIndexArg[i].mName; ++i)
if (type == sIndexArg[i].mType) if (type == sIndexArg[i].mType)
{ {
mArgumentType = ArgumentType_Index; mValue = int{};
mClass = sIndexArg[i].mClass; mClass = sIndexArg[i].mClass;
return; return;
} }
@ -261,10 +275,8 @@ CSMWorld::UniversalId::UniversalId(Type type)
} }
CSMWorld::UniversalId::UniversalId(Type type, const std::string& id) CSMWorld::UniversalId::UniversalId(Type type, const std::string& id)
: mArgumentType(ArgumentType_Id) : mType(type)
, mType(type) , mValue(id)
, mId(id)
, mIndex(0)
{ {
for (int i = 0; sIdArg[i].mName; ++i) for (int i = 0; sIdArg[i].mName; ++i)
if (type == sIdArg[i].mType) if (type == sIdArg[i].mType)
@ -281,9 +293,8 @@ CSMWorld::UniversalId::UniversalId(Type type, const ESM::RefId& id)
} }
CSMWorld::UniversalId::UniversalId(Type type, int index) CSMWorld::UniversalId::UniversalId(Type type, int index)
: mArgumentType(ArgumentType_Index) : mType(type)
, mType(type) , mValue(index)
, mIndex(index)
{ {
for (int i = 0; sIndexArg[i].mName; ++i) for (int i = 0; sIndexArg[i].mName; ++i)
if (type == sIndexArg[i].mType) if (type == sIndexArg[i].mType)
@ -302,7 +313,7 @@ CSMWorld::UniversalId::Class CSMWorld::UniversalId::getClass() const
CSMWorld::UniversalId::ArgumentType CSMWorld::UniversalId::getArgumentType() const CSMWorld::UniversalId::ArgumentType CSMWorld::UniversalId::getArgumentType() const
{ {
return mArgumentType; return static_cast<CSMWorld::UniversalId::ArgumentType>(mValue.index());
} }
CSMWorld::UniversalId::Type CSMWorld::UniversalId::getType() const CSMWorld::UniversalId::Type CSMWorld::UniversalId::getType() const
@ -312,61 +323,24 @@ CSMWorld::UniversalId::Type CSMWorld::UniversalId::getType() const
const std::string& CSMWorld::UniversalId::getId() const const std::string& CSMWorld::UniversalId::getId() const
{ {
if (mArgumentType != ArgumentType_Id) if (const std::string* result = std::get_if<std::string>(&mValue))
throw std::logic_error("invalid access to ID of non-ID UniversalId"); return *result;
return mId; throw std::logic_error("invalid access to ID of non-ID UniversalId");
} }
int CSMWorld::UniversalId::getIndex() const int CSMWorld::UniversalId::getIndex() const
{ {
if (mArgumentType != ArgumentType_Index) if (const int* result = std::get_if<int>(&mValue))
throw std::logic_error("invalid access to index of non-index UniversalId"); return *result;
return mIndex;
}
bool CSMWorld::UniversalId::isEqual(const UniversalId& universalId) const
{
if (mClass != universalId.mClass || mArgumentType != universalId.mArgumentType || mType != universalId.mType)
return false;
switch (mArgumentType)
{
case ArgumentType_Id:
return mId == universalId.mId;
case ArgumentType_Index:
return mIndex == universalId.mIndex;
default:
return true;
}
}
bool CSMWorld::UniversalId::isLess(const UniversalId& universalId) const
{
if (mType < universalId.mType)
return true;
if (mType > universalId.mType)
return false;
switch (mArgumentType) throw std::logic_error("invalid access to index of non-index UniversalId");
{
case ArgumentType_Id:
return mId < universalId.mId;
case ArgumentType_Index:
return mIndex < universalId.mIndex;
default:
return false;
}
} }
std::string CSMWorld::UniversalId::getTypeName() const std::string CSMWorld::UniversalId::getTypeName() const
{ {
const TypeData* typeData const TypeData* typeData
= mArgumentType == ArgumentType_None ? sNoArg : (mArgumentType == ArgumentType_Id ? sIdArg : sIndexArg); = getArgumentType() == ArgumentType_None ? sNoArg : (getArgumentType() == ArgumentType_Id ? sIdArg : sIndexArg);
for (int i = 0; typeData[i].mName; ++i) for (int i = 0; typeData[i].mName; ++i)
if (typeData[i].mType == mType) if (typeData[i].mType == mType)
@ -381,17 +355,7 @@ std::string CSMWorld::UniversalId::toString() const
stream << getTypeName(); stream << getTypeName();
switch (mArgumentType) std::visit(WriteToStream{ stream }, mValue);
{
case ArgumentType_None:
break;
case ArgumentType_Id:
stream << ": " << mId;
break;
case ArgumentType_Index:
stream << ": " << mIndex;
break;
}
return stream.str(); return stream.str();
} }
@ -399,7 +363,7 @@ std::string CSMWorld::UniversalId::toString() const
std::string CSMWorld::UniversalId::getIcon() const std::string CSMWorld::UniversalId::getIcon() const
{ {
const TypeData* typeData const TypeData* typeData
= mArgumentType == ArgumentType_None ? sNoArg : (mArgumentType == ArgumentType_Id ? sIdArg : sIndexArg); = getArgumentType() == ArgumentType_None ? sNoArg : (getArgumentType() == ArgumentType_Id ? sIdArg : sIndexArg);
for (int i = 0; typeData[i].mName; ++i) for (int i = 0; typeData[i].mName; ++i)
if (typeData[i].mType == mType) if (typeData[i].mType == mType)
@ -463,15 +427,10 @@ CSMWorld::UniversalId::Type CSMWorld::UniversalId::getParentType(Type type)
bool CSMWorld::operator==(const CSMWorld::UniversalId& left, const CSMWorld::UniversalId& right) bool CSMWorld::operator==(const CSMWorld::UniversalId& left, const CSMWorld::UniversalId& right)
{ {
return left.isEqual(right); return std::tie(left.mClass, left.mType, left.mValue) == std::tie(right.mClass, right.mType, right.mValue);
}
bool CSMWorld::operator!=(const CSMWorld::UniversalId& left, const CSMWorld::UniversalId& right)
{
return !left.isEqual(right);
} }
bool CSMWorld::operator<(const UniversalId& left, const UniversalId& right) bool CSMWorld::operator<(const UniversalId& left, const UniversalId& right)
{ {
return left.isLess(right); return std::tie(left.mClass, left.mType, left.mValue) < std::tie(right.mClass, right.mType, right.mValue);
} }

@ -2,6 +2,7 @@
#define CSM_WOLRD_UNIVERSALID_H #define CSM_WOLRD_UNIVERSALID_H
#include <string> #include <string>
#include <variant>
#include <vector> #include <vector>
#include <QMetaType> #include <QMetaType>
@ -31,7 +32,7 @@ namespace CSMWorld
{ {
ArgumentType_None, ArgumentType_None,
ArgumentType_Id, ArgumentType_Id,
ArgumentType_Index ArgumentType_Index,
}; };
/// \note A record list type must always be immediately followed by the matching /// \note A record list type must always be immediately followed by the matching
@ -144,14 +145,6 @@ namespace CSMWorld
NumberOfTypes = Type_RunLog + 1 NumberOfTypes = Type_RunLog + 1
}; };
private:
Class mClass;
ArgumentType mArgumentType;
Type mType;
std::string mId;
int mIndex;
public:
UniversalId(const std::string& universalId); UniversalId(const std::string& universalId);
UniversalId(Type type = Type_None); UniversalId(Type type = Type_None);
@ -176,10 +169,6 @@ namespace CSMWorld
int getIndex() const; int getIndex() const;
///< Calling this function for a non-index type will throw an exception. ///< Calling this function for a non-index type will throw an exception.
bool isEqual(const UniversalId& universalId) const;
bool isLess(const UniversalId& universalId) const;
std::string getTypeName() const; std::string getTypeName() const;
std::string toString() const; std::string toString() const;
@ -195,10 +184,18 @@ namespace CSMWorld
/// that contains records of type \a type. /// that contains records of type \a type.
/// Otherwise return Type_None. /// Otherwise return Type_None.
static Type getParentType(Type type); static Type getParentType(Type type);
private:
Class mClass;
Type mType;
std::variant<std::monostate, std::string, int> mValue;
friend bool operator==(const UniversalId& left, const UniversalId& right);
friend bool operator<(const UniversalId& left, const UniversalId& right);
}; };
bool operator==(const UniversalId& left, const UniversalId& right); bool operator==(const UniversalId& left, const UniversalId& right);
bool operator!=(const UniversalId& left, const UniversalId& right);
bool operator<(const UniversalId& left, const UniversalId& right); bool operator<(const UniversalId& left, const UniversalId& right);
} }

Loading…
Cancel
Save