1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-10-31 00:07:39 +02:00

Implemented compact serialization of integer numbers

This commit is contained in:
Ivan Savenko
2024-05-07 15:39:43 +00:00
parent 87eac164e6
commit cce3f1cb2d
3 changed files with 110 additions and 3 deletions

View File

@@ -177,12 +177,65 @@ public:
return * this;
}
template < class T, typename std::enable_if_t < std::is_fundamental_v<T> && !std::is_same_v<T, bool>, int > = 0 >
template< typename IntegerType>
void loadEncodedInteger(IntegerType & value)
{
using UnsignedType = std::make_unsigned_t<IntegerType>;
UnsignedType valueUnsigned = 0;
uint_fast8_t offset = 0;
for (;;)
{
uint8_t byteValue;
load(byteValue);
if ((byteValue & 0x80) != 0)
{
valueUnsigned |= (byteValue & 0x7f) << offset;
offset += 7;
}
else
{
valueUnsigned |= (byteValue & 0x3f) << offset;
if constexpr(std::is_signed_v<IntegerType>)
{
bool isNegative = (byteValue & 0x40) != 0;
if (isNegative)
value = -valueUnsigned;
else
value = valueUnsigned;
}
else
value = valueUnsigned;
return;
}
}
}
template < class T, typename std::enable_if_t < std::is_floating_point_v<T>, int > = 0 >
void load(T &data)
{
this->read(static_cast<void *>(&data), sizeof(data), reverseEndianness);
}
template < class T, typename std::enable_if_t < std::is_integral_v<T> && !std::is_same_v<T, bool>, int > = 0 >
void load(T &data)
{
if constexpr (sizeof(T) == 1)
{
this->read(static_cast<void *>(&data), sizeof(data), reverseEndianness);
}
else
{
if (hasFeature(Version::COMPACT_INTEGER_SERIALIZATION))
loadEncodedInteger(data);
else
this->read(static_cast<void *>(&data), sizeof(data), reverseEndianness);
}
}
template < typename T, typename std::enable_if_t < is_serializeable<BinaryDeserializer, T>::value, int > = 0 >
void load(T &data)
{
@@ -199,6 +252,11 @@ public:
load(data[i]);
}
void load(Version &data)
{
this->read(static_cast<void *>(&data), sizeof(data), reverseEndianness);
}
template < typename T, typename std::enable_if_t < std::is_enum_v<T>, int > = 0 >
void load(T &data)
{

View File

@@ -140,6 +140,32 @@ public:
return * this;
}
template< typename IntegerType>
void saveEncodedInteger(const IntegerType & value)
{
using UnsignedType = std::make_unsigned_t<IntegerType>;
UnsignedType valueUnsigned;
if constexpr(std::is_signed_v<IntegerType>)
valueUnsigned = std::abs(value);
else
valueUnsigned = value;
while (valueUnsigned > 0x3f)
{
uint8_t byteValue = (valueUnsigned & 0x7f) | 0x80;
valueUnsigned = valueUnsigned >> 7;
save(byteValue);
}
uint8_t lastByteValue = valueUnsigned & 0x3f;
if constexpr(std::is_signed_v<IntegerType>)
{
if (value < 0)
lastByteValue |= 0x40;
}
save(lastByteValue);
}
template < typename T, typename std::enable_if_t < std::is_same_v<T, bool>, int > = 0 >
void save(const T &data)
{
@@ -147,13 +173,35 @@ public:
save(writ);
}
template < class T, typename std::enable_if_t < std::is_fundamental_v<T> && !std::is_same_v<T, bool>, int > = 0 >
template < class T, typename std::enable_if_t < std::is_floating_point_v<T>, int > = 0 >
void save(const T &data)
{
// save primitive - simply dump binary data to output
this->write(static_cast<const void *>(&data), sizeof(data));
}
template < class T, typename std::enable_if_t < std::is_integral_v<T> && !std::is_same_v<T, bool>, int > = 0 >
void save(const T &data)
{
if constexpr (sizeof(T) == 1)
{
// save primitive - simply dump binary data to output
this->write(static_cast<const void *>(&data), sizeof(data));
}
else
{
if (hasFeature(Version::COMPACT_INTEGER_SERIALIZATION))
saveEncodedInteger(data);
else
this->write(static_cast<const void *>(&data), sizeof(data));
}
}
void save(const Version &data)
{
this->write(static_cast<const void *>(&data), sizeof(data));
}
template < typename T, typename std::enable_if_t < std::is_enum_v<T>, int > = 0 >
void save(const T &data)
{

View File

@@ -45,6 +45,7 @@ enum class ESerializationVersion : int32_t
RELEASE_150 = ARTIFACT_COSTUMES, // for convenience
COMPACT_STRING_SERIALIZATION,
COMPACT_INTEGER_SERIALIZATION,
CURRENT = COMPACT_STRING_SERIALIZATION
CURRENT = COMPACT_INTEGER_SERIALIZATION
};