瀏覽代碼

Implemented compact serialization of integer numbers

Ivan Savenko 1 年之前
父節點
當前提交
cce3f1cb2d
共有 3 個文件被更改,包括 110 次插入3 次删除
  1. 59 1
      lib/serializer/BinaryDeserializer.h
  2. 49 1
      lib/serializer/BinarySerializer.h
  3. 2 1
      lib/serializer/ESerializationVersion.h

+ 59 - 1
lib/serializer/BinaryDeserializer.h

@@ -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)
 	{

+ 49 - 1
lib/serializer/BinarySerializer.h

@@ -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)
 	{

+ 2 - 1
lib/serializer/ESerializationVersion.h

@@ -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
 };