Core/Serialization: Add bit serialization

Former-commit-id: dbaf3a2d40a85955b4d48efba72a5df9d92d0eb1
This commit is contained in:
Lynix 2015-11-23 13:45:35 +01:00
parent c93e4e901e
commit 7f220ce48c
6 changed files with 58 additions and 11 deletions

View File

@ -80,14 +80,33 @@ namespace Nz
inline bool Serialize(SerializationContext& context, bool value) inline bool Serialize(SerializationContext& context, bool value)
{ {
///TODO: Handle bits writing (Serializing 8 bits should only use one byte) if (context.currentBitPos == 8)
UInt8 buffer = (value) ? 1 : 0; {
return context.stream->Write(&buffer, 1) == 1; context.currentBitPos = 0;
context.currentByte = 0;
}
if (value)
context.currentByte |= 1 << context.currentBitPos;
if (++context.currentBitPos >= 8)
return Serialize<UInt8>(context, context.currentByte);
else
return true;
} }
template<typename T> template<typename T>
std::enable_if_t<std::is_arithmetic<T>::value, bool> Serialize(SerializationContext& context, T value) std::enable_if_t<std::is_arithmetic<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<UInt8>(context, context.currentByte))
NazaraWarning("Failed to flush bits");
}
if (context.endianness != Endianness_Unknown && context.endianness != GetPlatformEndianness()) if (context.endianness != Endianness_Unknown && context.endianness != GetPlatformEndianness())
SwapBytes(&value, sizeof(T)); SwapBytes(&value, sizeof(T));
@ -98,14 +117,20 @@ namespace Nz
{ {
NazaraAssert(value, "Invalid data pointer"); NazaraAssert(value, "Invalid data pointer");
UInt8 buffer; if (context.currentBitPos == 8)
if (context.stream->Read(&buffer, 1) == 1)
{ {
*value = (buffer == 1); if (!Unserialize(context, &context.currentByte))
return true;
}
else
return false; return false;
context.currentBitPos = 0;
}
if (value)
*value = (context.currentByte & (1 << context.currentBitPos)) != 0;
context.currentBitPos++;
return true;
} }
template<typename T> template<typename T>
@ -113,6 +138,9 @@ namespace Nz
{ {
NazaraAssert(value, "Invalid data pointer"); NazaraAssert(value, "Invalid data pointer");
// Reset bit position
context.currentBitPos = 8;
if (context.stream->Read(value, sizeof(T)) == sizeof(T)) if (context.stream->Read(value, sizeof(T)) == sizeof(T))
{ {
if (context.endianness != Endianness_Unknown && context.endianness != GetPlatformEndianness()) if (context.endianness != Endianness_Unknown && context.endianness != GetPlatformEndianness())

View File

@ -21,12 +21,16 @@ namespace Nz
{ {
Stream* stream; Stream* stream;
Endianness endianness; Endianness endianness;
UInt8 currentBitPos;
UInt8 currentByte;
}; };
struct UnserializationContext struct UnserializationContext
{ {
Stream* stream; Stream* stream;
Endianness endianness; Endianness endianness;
UInt8 currentBitPos;
UInt8 currentByte;
}; };
} }

View File

@ -20,7 +20,7 @@ namespace Nz
inline Serializer(Stream& stream); inline Serializer(Stream& stream);
Serializer(const Serializer&) = default; Serializer(const Serializer&) = default;
Serializer(Serializer&&) = default; Serializer(Serializer&&) = default;
~Serializer() = default; ~Serializer();
inline Endianness GetDataEndianness() const; inline Endianness GetDataEndianness() const;
inline Stream& GetStream() const; inline Stream& GetStream() const;

View File

@ -2,16 +2,29 @@
// This file is part of the "Nazara Engine - Core module" // This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Core/Debug.hpp> #include <Nazara/Core/Debug.hpp>
namespace Nz namespace Nz
{ {
inline Serializer::Serializer(Stream& stream) inline Serializer::Serializer(Stream& stream)
{ {
m_serializationContext.currentBitPos = 8;
m_serializationContext.endianness = Endianness_BigEndian; m_serializationContext.endianness = Endianness_BigEndian;
m_serializationContext.stream = &stream; 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<UInt8>(m_serializationContext, m_serializationContext.currentByte))
NazaraWarning("Failed to flush bits at serializer destruction");
}
}
inline Endianness Serializer::GetDataEndianness() const inline Endianness Serializer::GetDataEndianness() const
{ {
return m_serializationContext.endianness; return m_serializationContext.endianness;
@ -43,3 +56,4 @@ namespace Nz
} }
#include <Nazara/Core/DebugOff.hpp> #include <Nazara/Core/DebugOff.hpp>
#include "Serializer.hpp"

View File

@ -3,6 +3,7 @@
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include "Stream.hpp"
namespace Nz namespace Nz
{ {
@ -70,5 +71,4 @@ namespace Nz
return WriteBlock(buffer, size); return WriteBlock(buffer, size);
} }
} }

View File

@ -8,6 +8,7 @@ namespace Nz
{ {
inline Unserializer::Unserializer(Stream& stream) inline Unserializer::Unserializer(Stream& stream)
{ {
m_unserializationContext.currentBitPos = 8;
m_unserializationContext.endianness = Endianness_BigEndian; m_unserializationContext.endianness = Endianness_BigEndian;
m_unserializationContext.stream = &stream; m_unserializationContext.stream = &stream;
} }