mirror of https://github.com/OpenMW/openmw.git
Use serialized ESM::RefId for Lua records
parent
ca9c55ac26
commit
b7fdca0fe6
@ -1,24 +1,28 @@
|
||||
#include "formidrefid.hpp"
|
||||
|
||||
#include "serializerefid.hpp"
|
||||
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
std::string FormIdRefId::toString() const
|
||||
{
|
||||
return std::to_string(mValue);
|
||||
std::string result;
|
||||
result.resize(getIntegralSize(mValue) + 2, '\0');
|
||||
serializeIntegral(mValue, 0, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string FormIdRefId::toDebugString() const
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << *this;
|
||||
return stream.str();
|
||||
std::string result;
|
||||
serializeRefIdValue(mValue, formIdRefIdPrefix, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, FormIdRefId value)
|
||||
{
|
||||
return stream << "FormId{" << value.mValue << '}';
|
||||
return stream << value.toDebugString();
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,28 @@
|
||||
#include "generatedrefid.hpp"
|
||||
|
||||
#include "serializerefid.hpp"
|
||||
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
std::string GeneratedRefId::toString() const
|
||||
{
|
||||
return std::to_string(mValue);
|
||||
std::string result;
|
||||
result.resize(getIntegralSize(mValue) + 2, '\0');
|
||||
serializeIntegral(mValue, 0, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string GeneratedRefId::toDebugString() const
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << *this;
|
||||
return stream.str();
|
||||
std::string result;
|
||||
serializeRefIdValue(mValue, generatedRefIdPrefix, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, GeneratedRefId value)
|
||||
{
|
||||
return stream << "Generated{" << value.mValue << '}';
|
||||
return stream << value.toDebugString();
|
||||
}
|
||||
}
|
||||
|
@ -1,26 +1,33 @@
|
||||
#include "indexrefid.hpp"
|
||||
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include "serializerefid.hpp"
|
||||
|
||||
#include "esmcommon.hpp"
|
||||
#include <ostream>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
std::string IndexRefId::toString() const
|
||||
{
|
||||
return ESM::NAME(mRecordType).toString() + ", " + std::to_string(mValue);
|
||||
std::string result;
|
||||
result.resize(sizeof(mRecordType) + getIntegralSize(mValue) + 3, '\0');
|
||||
std::memcpy(result.data(), &mRecordType, sizeof(mRecordType));
|
||||
result[sizeof(mRecordType)] = ':';
|
||||
serializeIntegral(mValue, sizeof(mRecordType) + 1, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string IndexRefId::toDebugString() const
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << *this;
|
||||
return stream.str();
|
||||
std::string result;
|
||||
serializeRefIdPrefix(sizeof(mRecordType) + getIntegralSize(mValue) + 1, indexRefIdPrefix, result);
|
||||
std::memcpy(result.data() + indexRefIdPrefix.size(), &mRecordType, sizeof(mRecordType));
|
||||
result[indexRefIdPrefix.size() + sizeof(mRecordType)] = ':';
|
||||
serializeIntegral(mValue, indexRefIdPrefix.size() + sizeof(mRecordType) + 1, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, IndexRefId value)
|
||||
{
|
||||
return stream << "Index{" << ESM::NAME(value.mRecordType).toStringView() << ", " << value.mValue << '}';
|
||||
return stream << value.toDebugString();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,64 @@
|
||||
#ifndef OPENMW_COMPONENTS_ESM_SERIALIZEREFID_HPP
|
||||
#define OPENMW_COMPONENTS_ESM_SERIALIZEREFID_HPP
|
||||
|
||||
#include <charconv>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <system_error>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
constexpr std::string_view formIdRefIdPrefix = "FormId:";
|
||||
constexpr std::string_view generatedRefIdPrefix = "Generated:";
|
||||
constexpr std::string_view indexRefIdPrefix = "Index:";
|
||||
|
||||
template <class T>
|
||||
std::size_t getIntegralSize(T value)
|
||||
{
|
||||
std::size_t result = sizeof(T) * 2;
|
||||
while (true)
|
||||
{
|
||||
if (result == 1 || (value & static_cast<T>(0xf) << ((result - 1) * 4)) != 0)
|
||||
break;
|
||||
--result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void serializeRefIdPrefix(std::size_t valueSize, std::string_view prefix, std::string& out)
|
||||
{
|
||||
out.resize(prefix.size() + valueSize + 2, '\0');
|
||||
std::memcpy(out.data(), prefix.data(), prefix.size());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void serializeIntegral(T value, std::size_t shift, std::string& out)
|
||||
{
|
||||
out[shift] = '0';
|
||||
out[shift + 1] = 'x';
|
||||
const auto r = std::to_chars(out.data() + shift + 2, out.data() + out.size(), value, 16);
|
||||
if (r.ec != std::errc())
|
||||
throw std::system_error(std::make_error_code(r.ec), "Failed to serialize ESM::RefId integral value");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void serializeRefIdValue(T value, std::string_view prefix, std::string& out)
|
||||
{
|
||||
serializeRefIdPrefix(getIntegralSize(value), prefix, out);
|
||||
serializeIntegral(value, prefix.size(), out);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T deserializeIntegral(std::size_t shift, std::string_view value)
|
||||
{
|
||||
T result{};
|
||||
const auto r = std::from_chars(value.data() + shift + 2, value.data() + value.size(), result, 16);
|
||||
if (r.ec != std::errc())
|
||||
throw std::system_error(std::make_error_code(r.ec),
|
||||
"Failed to deserialize ESM::RefId integral value: \"" + std::string(value) + '"');
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue