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:
		| @@ -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) | ||||
| 	{ | ||||
|   | ||||
| @@ -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) | ||||
| 	{ | ||||
|   | ||||
| @@ -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 | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user