1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-19 21:23:54 +00:00
openmw/components/esm3/variant.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

279 lines
6.9 KiB
C++
Raw Normal View History

2013-03-04 12:59:06 +00:00
#include "variant.hpp"
#include <stdexcept>
#include "esmreader.hpp"
#include "variantimp.hpp"
namespace ESM
{
2014-06-03 20:35:26 +00:00
namespace
2013-03-04 12:59:06 +00:00
{
2021-05-13 14:18:28 +00:00
constexpr uint32_t STRV = fourCC("STRV");
constexpr uint32_t INTV = fourCC("INTV");
constexpr uint32_t FLTV = fourCC("FLTV");
constexpr uint32_t STTV = fourCC("STTV");
2013-03-04 12:59:06 +00:00
template <typename T, bool orDefault = false>
2021-05-13 14:18:28 +00:00
struct GetValue
{
2023-10-24 17:25:52 +00:00
constexpr T operator()(int32_t value) const { return static_cast<T>(value); }
2013-03-04 12:59:06 +00:00
constexpr T operator()(float value) const { return static_cast<T>(value); }
template <typename V>
constexpr T operator()(const V&) const
{
if constexpr (orDefault)
return T{};
else
throw std::runtime_error("cannot convert variant");
}
2022-09-22 18:26:05 +00:00
};
template <typename T>
struct SetValue
{
T mValue;
2013-03-04 12:59:06 +00:00
explicit SetValue(T value)
: mValue(value)
{
}
2023-10-24 17:25:52 +00:00
void operator()(int32_t& value) const { value = static_cast<int32_t>(mValue); }
2013-03-04 12:59:06 +00:00
void operator()(float& value) const { value = static_cast<float>(mValue); }
2013-03-04 12:59:06 +00:00
template <typename V>
void operator()(V&) const
2022-09-22 18:26:05 +00:00
{
throw std::runtime_error("cannot convert variant");
2022-09-22 18:26:05 +00:00
}
};
2013-03-04 12:59:06 +00:00
}
const std::string& Variant::getString() const
2013-03-04 12:59:06 +00:00
{
return std::get<std::string>(mData);
2013-03-04 12:59:06 +00:00
}
2023-10-24 17:25:52 +00:00
int32_t Variant::getInteger() const
2013-03-04 12:59:06 +00:00
{
2023-10-24 17:25:52 +00:00
return std::visit(GetValue<int32_t>{}, mData);
2022-09-22 18:26:05 +00:00
}
2013-03-04 12:59:06 +00:00
float Variant::getFloat() const
{
return std::visit(GetValue<float>{}, mData);
}
2022-09-22 18:26:05 +00:00
void Variant::read(ESMReader& esm, Format format)
2013-03-04 12:59:06 +00:00
{
2022-09-22 18:26:05 +00:00
// type
2013-03-04 12:59:06 +00:00
VarType type = VT_Unknown;
2022-09-22 18:26:05 +00:00
2013-03-05 07:02:05 +00:00
if (format == Format_Global)
2013-03-04 12:59:06 +00:00
{
std::string typeId = esm.getHNString("FNAM");
2022-09-22 18:26:05 +00:00
2013-03-04 12:59:06 +00:00
if (typeId == "s")
type = VT_Short;
else if (typeId == "l")
2013-03-05 07:02:05 +00:00
type = VT_Long;
2013-03-04 12:59:06 +00:00
else if (typeId == "f")
type = VT_Float;
2022-09-22 18:26:05 +00:00
else
2013-03-04 12:59:06 +00:00
esm.fail("illegal global variable type " + typeId);
}
2013-03-05 07:02:05 +00:00
else if (format == Format_Gmst)
2022-09-22 18:26:05 +00:00
{
2013-03-05 07:02:05 +00:00
if (!esm.hasMoreSubs())
2022-09-22 18:26:05 +00:00
{
2013-03-04 12:59:06 +00:00
type = VT_None;
2022-09-22 18:26:05 +00:00
}
else
{
2013-03-05 07:02:05 +00:00
esm.getSubName();
NAME name = esm.retSubName();
2022-09-22 18:26:05 +00:00
2014-06-03 20:35:26 +00:00
if (name == STRV)
2022-09-22 18:26:05 +00:00
{
2013-03-05 07:02:05 +00:00
type = VT_String;
2022-09-22 18:26:05 +00:00
}
2014-06-03 20:35:26 +00:00
else if (name == INTV)
2022-09-22 18:26:05 +00:00
{
2013-03-05 07:02:05 +00:00
type = VT_Int;
2022-09-22 18:26:05 +00:00
}
2014-06-03 20:35:26 +00:00
else if (name == FLTV)
2022-09-22 18:26:05 +00:00
{
2013-03-05 07:02:05 +00:00
type = VT_Float;
2022-09-22 18:26:05 +00:00
}
else
2013-03-05 07:02:05 +00:00
esm.fail("invalid subrecord: " + name.toString());
2022-09-22 18:26:05 +00:00
}
}
else if (format == Format_Info)
2013-03-04 12:59:06 +00:00
{
2013-03-05 07:02:05 +00:00
esm.getSubName();
NAME name = esm.retSubName();
2014-06-03 20:35:26 +00:00
if (name == INTV)
2013-03-05 07:02:05 +00:00
{
type = VT_Int;
2022-09-22 18:26:05 +00:00
}
2014-06-03 20:35:26 +00:00
else if (name == FLTV)
2022-09-22 18:26:05 +00:00
{
type = VT_Float;
2013-03-05 07:02:05 +00:00
}
2014-06-03 20:35:26 +00:00
else
esm.fail("invalid subrecord: " + name.toString());
2022-09-22 18:26:05 +00:00
}
else if (format == Format_Local)
2022-09-22 18:26:05 +00:00
{
esm.getSubName();
NAME name = esm.retSubName();
2022-09-22 18:26:05 +00:00
2014-06-03 20:35:26 +00:00
if (name == INTV)
2013-03-05 07:02:05 +00:00
{
type = VT_Int;
}
2014-06-03 20:35:26 +00:00
else if (name == FLTV)
2013-03-05 07:02:05 +00:00
{
type = VT_Float;
}
else if (name == STTV)
2022-09-22 18:26:05 +00:00
{
type = VT_Short;
2022-09-22 18:26:05 +00:00
}
2013-03-05 07:02:05 +00:00
else
esm.fail("invalid subrecord: " + name.toString());
2013-03-04 12:59:06 +00:00
}
setType(type);
2022-09-22 18:26:05 +00:00
std::visit(ReadESMVariantValue{ esm, format, mType }, mData);
}
void Variant::write(ESMWriter& esm, Format format) const
{
if (mType == VT_Unknown)
{
throw std::runtime_error("can not serialise variant of unknown type");
}
else if (mType == VT_None)
{
if (format == Format_Global)
2013-03-04 12:59:06 +00:00
throw std::runtime_error("can not serialise variant of type none to global format");
if (format == Format_Info)
throw std::runtime_error("can not serialise variant of type none to info format");
if (format == Format_Local)
throw std::runtime_error("can not serialise variant of type none to local format");
2013-03-04 12:59:06 +00:00
// nothing to do here for GMST format
2022-09-22 18:26:05 +00:00
}
else
std::visit(WriteESMVariantValue{ esm, format, mType }, mData);
2013-03-04 12:59:06 +00:00
}
void Variant::write(std::ostream& stream) const
2013-03-04 12:59:06 +00:00
{
switch (mType)
2022-09-22 18:26:05 +00:00
{
2013-03-04 12:59:06 +00:00
case VT_Unknown:
stream << "variant unknown";
2022-09-22 18:26:05 +00:00
break;
2013-03-04 12:59:06 +00:00
case VT_None:
2013-03-04 12:59:06 +00:00
stream << "variant none";
2022-09-22 18:26:05 +00:00
break;
2013-03-04 12:59:06 +00:00
case VT_Short:
2013-03-04 12:59:06 +00:00
2023-10-24 17:25:52 +00:00
stream << "variant short: " << std::get<int32_t>(mData);
2022-09-22 18:26:05 +00:00
break;
2013-03-04 12:59:06 +00:00
case VT_Int:
2013-03-04 12:59:06 +00:00
2023-10-24 17:25:52 +00:00
stream << "variant int: " << std::get<int32_t>(mData);
break;
2013-03-04 12:59:06 +00:00
case VT_Long:
2022-09-22 18:26:05 +00:00
2023-10-24 17:25:52 +00:00
stream << "variant long: " << std::get<int32_t>(mData);
2013-03-04 12:59:06 +00:00
break;
case VT_Float:
2022-09-22 18:26:05 +00:00
stream << "variant float: " << std::get<float>(mData);
2013-03-04 12:59:06 +00:00
break;
case VT_String:
2022-09-22 18:26:05 +00:00
stream << "variant string: \"" << std::get<std::string>(mData) << "\"";
2013-03-04 12:59:06 +00:00
break;
}
2022-09-22 18:26:05 +00:00
}
2013-03-04 12:59:06 +00:00
void Variant::setType(VarType type)
2022-09-22 18:26:05 +00:00
{
2013-03-04 12:59:06 +00:00
if (type != mType)
2022-09-22 18:26:05 +00:00
{
2013-03-04 12:59:06 +00:00
switch (type)
2022-09-22 18:26:05 +00:00
{
2013-03-04 12:59:06 +00:00
case VT_Unknown:
case VT_None:
mData = std::monostate{};
2022-09-22 18:26:05 +00:00
break;
2013-03-04 12:59:06 +00:00
case VT_Short:
case VT_Int:
case VT_Long:
mData = std::visit(GetValue<int, true>{}, mData);
2022-09-22 18:26:05 +00:00
break;
2013-03-04 12:59:06 +00:00
case VT_Float:
mData = std::visit(GetValue<float, true>{}, mData);
2022-09-22 18:26:05 +00:00
break;
2013-03-04 12:59:06 +00:00
case VT_String:
mData = std::string{};
2022-09-22 18:26:05 +00:00
break;
}
2013-03-04 12:59:06 +00:00
mType = type;
2022-09-22 18:26:05 +00:00
}
2013-03-04 12:59:06 +00:00
}
void Variant::setString(const std::string& value)
2013-03-04 12:59:06 +00:00
{
std::get<std::string>(mData) = value;
2013-03-04 12:59:06 +00:00
}
void Variant::setString(std::string&& value)
2013-03-04 12:59:06 +00:00
{
std::get<std::string>(mData) = std::move(value);
2013-03-04 12:59:06 +00:00
}
2023-10-24 17:25:52 +00:00
void Variant::setInteger(int32_t value)
2013-03-04 12:59:06 +00:00
{
std::visit(SetValue(value), mData);
2013-03-04 12:59:06 +00:00
}
void Variant::setFloat(float value)
2013-03-04 12:59:06 +00:00
{
std::visit(SetValue(value), mData);
2013-03-04 12:59:06 +00:00
}
std::ostream& operator<<(std::ostream& stream, const Variant& value)
2013-03-04 12:59:06 +00:00
{
value.write(stream);
return stream;
}
}