diff --git a/include/Nazara/Core/Algorithm.inl b/include/Nazara/Core/Algorithm.inl index 6e3d8853a..2e9661dd9 100644 --- a/include/Nazara/Core/Algorithm.inl +++ b/include/Nazara/Core/Algorithm.inl @@ -80,14 +80,33 @@ namespace Nz inline bool Serialize(SerializationContext& context, bool value) { - ///TODO: Handle bits writing (Serializing 8 bits should only use one byte) - UInt8 buffer = (value) ? 1 : 0; - return context.stream->Write(&buffer, 1) == 1; + if (context.currentBitPos == 8) + { + context.currentBitPos = 0; + context.currentByte = 0; + } + + if (value) + context.currentByte |= 1 << context.currentBitPos; + + if (++context.currentBitPos >= 8) + return Serialize(context, context.currentByte); + else + return true; } template std::enable_if_t::value, bool> Serialize(SerializationContext& context, T value) { + // Flush bits if a writing is in progress + if (context.currentBitPos != 8) + { + context.currentBitPos = 8; + + if (!Serialize(context, context.currentByte)) + NazaraWarning("Failed to flush bits"); + } + if (context.endianness != Endianness_Unknown && context.endianness != GetPlatformEndianness()) SwapBytes(&value, sizeof(T)); @@ -98,14 +117,20 @@ namespace Nz { NazaraAssert(value, "Invalid data pointer"); - UInt8 buffer; - if (context.stream->Read(&buffer, 1) == 1) + if (context.currentBitPos == 8) { - *value = (buffer == 1); - return true; + if (!Unserialize(context, &context.currentByte)) + return false; + + context.currentBitPos = 0; } - else - return false; + + if (value) + *value = (context.currentByte & (1 << context.currentBitPos)) != 0; + + context.currentBitPos++; + + return true; } template @@ -113,6 +138,9 @@ namespace Nz { NazaraAssert(value, "Invalid data pointer"); + // Reset bit position + context.currentBitPos = 8; + if (context.stream->Read(value, sizeof(T)) == sizeof(T)) { if (context.endianness != Endianness_Unknown && context.endianness != GetPlatformEndianness()) diff --git a/include/Nazara/Core/Serialization.hpp b/include/Nazara/Core/Serialization.hpp index 36e77caea..409aa6ace 100644 --- a/include/Nazara/Core/Serialization.hpp +++ b/include/Nazara/Core/Serialization.hpp @@ -21,12 +21,16 @@ namespace Nz { Stream* stream; Endianness endianness; + UInt8 currentBitPos; + UInt8 currentByte; }; struct UnserializationContext { Stream* stream; Endianness endianness; + UInt8 currentBitPos; + UInt8 currentByte; }; } diff --git a/include/Nazara/Core/Serializer.hpp b/include/Nazara/Core/Serializer.hpp index 95ca33190..994e85a19 100644 --- a/include/Nazara/Core/Serializer.hpp +++ b/include/Nazara/Core/Serializer.hpp @@ -20,7 +20,7 @@ namespace Nz inline Serializer(Stream& stream); Serializer(const Serializer&) = default; Serializer(Serializer&&) = default; - ~Serializer() = default; + ~Serializer(); inline Endianness GetDataEndianness() const; inline Stream& GetStream() const; diff --git a/include/Nazara/Core/Serializer.inl b/include/Nazara/Core/Serializer.inl index a61315090..168d7f812 100644 --- a/include/Nazara/Core/Serializer.inl +++ b/include/Nazara/Core/Serializer.inl @@ -2,16 +2,29 @@ // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp +#include #include namespace Nz { inline Serializer::Serializer(Stream& stream) { + m_serializationContext.currentBitPos = 8; m_serializationContext.endianness = Endianness_BigEndian; m_serializationContext.stream = &stream; } + inline Serializer::~Serializer() + { + if (m_serializationContext.currentBitPos != 8) + { + m_serializationContext.currentBitPos = 8; //< To prevent Serialize to flush bits itself + + if (!Serialize(m_serializationContext, m_serializationContext.currentByte)) + NazaraWarning("Failed to flush bits at serializer destruction"); + } + } + inline Endianness Serializer::GetDataEndianness() const { return m_serializationContext.endianness; @@ -43,3 +56,4 @@ namespace Nz } #include +#include "Serializer.hpp" diff --git a/include/Nazara/Core/Stream.inl b/include/Nazara/Core/Stream.inl index a7e17a099..6c5098060 100644 --- a/include/Nazara/Core/Stream.inl +++ b/include/Nazara/Core/Stream.inl @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include "Stream.hpp" namespace Nz { @@ -70,5 +71,4 @@ namespace Nz return WriteBlock(buffer, size); } - } diff --git a/include/Nazara/Core/Unserializer.inl b/include/Nazara/Core/Unserializer.inl index 97f91214f..3a832504a 100644 --- a/include/Nazara/Core/Unserializer.inl +++ b/include/Nazara/Core/Unserializer.inl @@ -8,6 +8,7 @@ namespace Nz { inline Unserializer::Unserializer(Stream& stream) { + m_unserializationContext.currentBitPos = 8; m_unserializationContext.endianness = Endianness_BigEndian; m_unserializationContext.stream = &stream; }