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 <sstream>
#include <stdexcept>
#include <tuple>
#include <vector>
namespace
@ -178,10 +179,23 @@ namespace
// end marker
{ 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)
: mIndex(0)
: mValue(std::monostate{})
{
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)
if (type == sIdArg[i].mName)
{
mArgumentType = ArgumentType_Id;
mType = sIdArg[i].mType;
mClass = sIdArg[i].mClass;
mId = universalId.substr(index + 2);
mValue = universalId.substr(index + 2);
return;
}
for (int i = 0; sIndexArg[i].mName; ++i)
if (type == sIndexArg[i].mName)
{
mArgumentType = ArgumentType_Index;
mType = sIndexArg[i].mType;
mClass = sIndexArg[i].mClass;
std::istringstream stream(universalId.substr(index + 2));
if (stream >> mIndex)
int index = 0;
if (stream >> index)
{
mValue = index;
return;
}
break;
}
@ -219,7 +235,6 @@ CSMWorld::UniversalId::UniversalId(const std::string& universalId)
for (int i = 0; sNoArg[i].mName; ++i)
if (universalId == sNoArg[i].mName)
{
mArgumentType = ArgumentType_None;
mType = sNoArg[i].mType;
mClass = sNoArg[i].mClass;
return;
@ -230,9 +245,8 @@ CSMWorld::UniversalId::UniversalId(const std::string& universalId)
}
CSMWorld::UniversalId::UniversalId(Type type)
: mArgumentType(ArgumentType_None)
, mType(type)
, mIndex(0)
: mType(type)
, mValue(std::monostate{})
{
for (int i = 0; sNoArg[i].mName; ++i)
if (type == sNoArg[i].mType)
@ -244,7 +258,7 @@ CSMWorld::UniversalId::UniversalId(Type type)
for (int i = 0; sIdArg[i].mName; ++i)
if (type == sIdArg[i].mType)
{
mArgumentType = ArgumentType_Id;
mValue = std::string();
mClass = sIdArg[i].mClass;
return;
}
@ -252,7 +266,7 @@ CSMWorld::UniversalId::UniversalId(Type type)
for (int i = 0; sIndexArg[i].mName; ++i)
if (type == sIndexArg[i].mType)
{
mArgumentType = ArgumentType_Index;
mValue = int{};
mClass = sIndexArg[i].mClass;
return;
}
@ -261,10 +275,8 @@ CSMWorld::UniversalId::UniversalId(Type type)
}
CSMWorld::UniversalId::UniversalId(Type type, const std::string& id)
: mArgumentType(ArgumentType_Id)
, mType(type)
, mId(id)
, mIndex(0)
: mType(type)
, mValue(id)
{
for (int i = 0; sIdArg[i].mName; ++i)
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)
: mArgumentType(ArgumentType_Index)
, mType(type)
, mIndex(index)
: mType(type)
, mValue(index)
{
for (int i = 0; sIndexArg[i].mName; ++i)
if (type == sIndexArg[i].mType)
@ -302,7 +313,7 @@ CSMWorld::UniversalId::Class CSMWorld::UniversalId::getClass() 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
@ -312,61 +323,24 @@ CSMWorld::UniversalId::Type CSMWorld::UniversalId::getType() const
const std::string& CSMWorld::UniversalId::getId() const
{
if (mArgumentType != ArgumentType_Id)
throw std::logic_error("invalid access to ID of non-ID UniversalId");
if (const std::string* result = std::get_if<std::string>(&mValue))
return *result;
return mId;
throw std::logic_error("invalid access to ID of non-ID UniversalId");
}
int CSMWorld::UniversalId::getIndex() const
{
if (mArgumentType != ArgumentType_Index)
throw std::logic_error("invalid access to index of non-index UniversalId");
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;
if (const int* result = std::get_if<int>(&mValue))
return *result;
switch (mArgumentType)
{
case ArgumentType_Id:
return mId < universalId.mId;
case ArgumentType_Index:
return mIndex < universalId.mIndex;
default:
return false;
}
throw std::logic_error("invalid access to index of non-index UniversalId");
}
std::string CSMWorld::UniversalId::getTypeName() const
{
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)
if (typeData[i].mType == mType)
@ -381,17 +355,7 @@ std::string CSMWorld::UniversalId::toString() const
stream << getTypeName();
switch (mArgumentType)
{
case ArgumentType_None:
break;
case ArgumentType_Id:
stream << ": " << mId;
break;
case ArgumentType_Index:
stream << ": " << mIndex;
break;
}
std::visit(WriteToStream{ stream }, mValue);
return stream.str();
}
@ -399,7 +363,7 @@ std::string CSMWorld::UniversalId::toString() const
std::string CSMWorld::UniversalId::getIcon() const
{
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)
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)
{
return left.isEqual(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 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
#include <string>
#include <variant>
#include <vector>
#include <QMetaType>
@ -31,7 +32,7 @@ namespace CSMWorld
{
ArgumentType_None,
ArgumentType_Id,
ArgumentType_Index
ArgumentType_Index,
};
/// \note A record list type must always be immediately followed by the matching
@ -144,14 +145,6 @@ namespace CSMWorld
NumberOfTypes = Type_RunLog + 1
};
private:
Class mClass;
ArgumentType mArgumentType;
Type mType;
std::string mId;
int mIndex;
public:
UniversalId(const std::string& universalId);
UniversalId(Type type = Type_None);
@ -176,10 +169,6 @@ namespace CSMWorld
int getIndex() const;
///< 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 toString() const;
@ -195,10 +184,18 @@ namespace CSMWorld
/// that contains records of type \a type.
/// Otherwise return Type_None.
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);
}

Loading…
Cancel
Save