mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-21 17:41:36 +00:00
Implement UniversalId with std::variant
This commit is contained in:
parent
f2a3462e59
commit
4cd5efc6ee
2 changed files with 52 additions and 96 deletions
|
@ -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;
|
throw std::logic_error("invalid access to index of non-index UniversalId");
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
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…
Reference in a new issue