Core: Rework Serialization

Former-commit-id: d97eedbd3efc92235e3880ad061a5216fa77ebd7
This commit is contained in:
Lynix
2016-02-03 18:42:19 +01:00
parent f0863d9055
commit e367ec456d
17 changed files with 337 additions and 273 deletions

View File

@@ -41,10 +41,10 @@ namespace Nz
template<typename T>
std::enable_if_t<std::is_arithmetic<T>::value, bool> Serialize(SerializationContext& context, T value);
inline bool Unserialize(UnserializationContext& context, bool* value);
inline bool Unserialize(SerializationContext& context, bool* value);
template<typename T>
std::enable_if_t<std::is_arithmetic<T>::value, bool> Unserialize(UnserializationContext& context, T* value);
std::enable_if_t<std::is_arithmetic<T>::value, bool> Unserialize(SerializationContext& context, T* value);
}
#include <Nazara/Core/Algorithm.inl>

View File

@@ -131,10 +131,8 @@ namespace Nz
return context.stream->Write(&value, sizeof(T)) == sizeof(T);
}
inline bool Unserialize(UnserializationContext& context, bool* value)
inline bool Unserialize(SerializationContext& context, bool* value)
{
NazaraAssert(value, "Invalid data pointer");
if (context.currentBitPos == 8)
{
if (!Unserialize(context, &context.currentByte))
@@ -152,7 +150,7 @@ namespace Nz
}
template<typename T>
std::enable_if_t<std::is_arithmetic<T>::value, bool> Unserialize(UnserializationContext& context, T* value)
std::enable_if_t<std::is_arithmetic<T>::value, bool> Unserialize(SerializationContext& context, T* value)
{
NazaraAssert(value, "Invalid data pointer");

View File

@@ -0,0 +1,65 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_BYTESTREAM_HPP
#define NAZARA_BYTESTREAM_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/ByteArray.hpp>
#include <Nazara/Core/Serialization.hpp>
#include <Nazara/Core/Stream.hpp>
#include <memory>
namespace Nz
{
class NAZARA_CORE_API ByteStream
{
public:
inline ByteStream(Stream* stream = nullptr);
ByteStream(ByteArray* byteArray, UInt32 openMode = OpenMode_ReadWrite);
ByteStream(void* ptr, Nz::UInt64 size);
ByteStream(const void* ptr, Nz::UInt64 size);
ByteStream(const ByteStream&) = delete;
inline ByteStream(ByteStream&& stream);
~ByteStream();
inline Endianness GetDataEndianness() const;
inline Nz::UInt64 GetSize() const;
inline Stream* GetStream() const;
inline bool FlushBits();
inline std::size_t Read(void* ptr, std::size_t size);
inline void SetDataEndianness(Endianness endiannes);
inline void SetStream(Stream* stream);
void SetStream(ByteArray* byteArray, UInt32 openMode = OpenMode_ReadWrite);
void SetStream(void* ptr, Nz::UInt64 size);
void SetStream(const void* ptr, Nz::UInt64 size);
inline void Write(const void* data, std::size_t size);
template<typename T>
ByteStream& operator>>(T& value);
template<typename T>
ByteStream& operator<<(const T& value);
ByteStream& operator=(const ByteStream&) = delete;
inline ByteStream& operator=(ByteStream&&);
private:
virtual void OnEmptyStream();
std::unique_ptr<Stream> m_ownedStream;
SerializationContext m_context;
};
}
#include <Nazara/Core/ByteStream.inl>
#endif // NAZARA_BYTESTREAM_HPP

View File

@@ -0,0 +1,129 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
inline ByteStream::ByteStream(Stream* stream)
{
m_context.stream = stream;
}
inline ByteStream::ByteStream(ByteStream&& stream) :
m_ownedStream(std::move(stream.m_ownedStream)),
m_context(stream.m_context)
{
stream.m_context.stream = nullptr;
}
inline ByteStream::~ByteStream()
{
if (!FlushBits())
NazaraWarning("Failed to flush bits at serializer destruction");
}
inline Endianness ByteStream::GetDataEndianness() const
{
return m_context.endianness;
}
inline Nz::UInt64 ByteStream::GetSize() const
{
if (m_context.stream)
return m_context.stream->GetSize();
else
return 0;
}
inline Stream* ByteStream::GetStream() const
{
return m_context.stream;
}
inline bool ByteStream::FlushBits()
{
if (!m_context.stream)
return true;
if (m_context.currentBitPos != 8)
{
m_context.currentBitPos = 8; //< To prevent Serialize to flush bits itself
if (!Serialize<UInt8>(m_context, m_context.currentByte))
return false;
}
return true;
}
inline std::size_t ByteStream::Read(void* ptr, std::size_t size)
{
if (!m_context.stream)
OnEmptyStream();
FlushBits();
return m_context.stream->Read(ptr, size);
}
inline void ByteStream::SetDataEndianness(Endianness endiannes)
{
m_context.endianness = endiannes;
}
inline void ByteStream::SetStream(Stream* stream)
{
// We don't want to lose some bits..
FlushBits();
m_context.stream = stream;
m_ownedStream.reset();
}
inline void ByteStream::Write(const void* data, std::size_t size)
{
if (!m_context.stream)
OnEmptyStream();
FlushBits();
m_context.stream->Write(data, size);
}
template<typename T>
ByteStream& ByteStream::operator>>(T& value)
{
if (!m_context.stream)
OnEmptyStream();
if (!Unserialize(m_context, &value))
NazaraError("Failed to serialize value");
return *this;
}
template<typename T>
ByteStream& ByteStream::operator<<(const T& value)
{
if (!m_context.stream)
OnEmptyStream();
if (!Serialize(m_context, value))
NazaraError("Failed to serialize value");
return *this;
}
inline ByteStream& ByteStream::operator=(ByteStream&& stream)
{
m_context = stream.m_context;
m_ownedStream = std::move(stream.m_ownedStream);
stream.m_context.stream = nullptr;
return *this;
}
}
#include <Nazara/Core/DebugOff.hpp>

View File

@@ -8,16 +8,17 @@
#define NAZARA_MEMORYSTREAM_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/ByteArray.hpp>
#include <Nazara/Core/Stream.hpp>
namespace Nz
{
class ByteArray;
class NAZARA_CORE_API MemoryStream : public Stream
{
public:
MemoryStream();
MemoryStream(const void* ptr, unsigned int size);
inline MemoryStream();
inline MemoryStream(ByteArray* byteArray, UInt32 openMode = OpenMode_ReadWrite);
MemoryStream(const MemoryStream&) = default;
MemoryStream(MemoryStream&&) = default;
~MemoryStream() = default;
@@ -26,11 +27,12 @@ namespace Nz
bool EndOfStream() const override;
const ByteArray& GetBuffer() const;
const UInt8* GetData() const;
inline ByteArray& GetBuffer();
inline const ByteArray& GetBuffer() const;
UInt64 GetCursorPos() const override;
UInt64 GetSize() const override;
void SetBuffer(ByteArray* byteArray, UInt32 openMode = OpenMode_ReadWrite);
bool SetCursorPos(UInt64 offset) override;
MemoryStream& operator=(const MemoryStream&) = default;
@@ -41,15 +43,9 @@ namespace Nz
std::size_t ReadBlock(void* buffer, std::size_t size) override;
std::size_t WriteBlock(const void* buffer, std::size_t size) override;
ByteArray m_buffer;
ByteArray* m_buffer;
UInt64 m_pos;
};
class AbstractHash;
inline bool HashAppend(AbstractHash* hash, const String& string);
NAZARA_CORE_API bool Serialize(SerializationContext& context, const String& string);
NAZARA_CORE_API bool Unserialize(UnserializationContext& context, String* string);
}
#include <Nazara/Core/MemoryStream.inl>

View File

@@ -2,13 +2,35 @@
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
inline bool HashAppend(AbstractHash* hash, const MemoryStream& stream)
inline MemoryStream::MemoryStream() :
Stream(StreamOption_None, OpenMode_ReadWrite),
m_pos(0)
{
return HashAppend(hash, stream.GetBuffer());
}
inline MemoryStream::MemoryStream(ByteArray* byteArray, UInt32 openMode) :
MemoryStream()
{
SetBuffer(byteArray, openMode);
}
inline ByteArray& MemoryStream::GetBuffer()
{
NazaraAssert(m_buffer, "Invalid buffer");
return *m_buffer;
}
inline const ByteArray& MemoryStream::GetBuffer() const
{
NazaraAssert(m_buffer, "Invalid buffer");
return *m_buffer;
}
}

View File

@@ -15,6 +15,7 @@ namespace Nz
class NAZARA_CORE_API MemoryView : public Stream
{
public:
MemoryView(void* ptr, UInt64 size);
MemoryView(const void* ptr, UInt64 size);
MemoryView(const MemoryView&) = delete;
MemoryView(MemoryView&&) = delete; ///TODO
@@ -35,7 +36,7 @@ namespace Nz
std::size_t ReadBlock(void* buffer, std::size_t size) override;
std::size_t WriteBlock(const void* buffer, std::size_t size) override;
const UInt8* m_ptr;
UInt8* m_ptr;
UInt64 m_pos;
UInt64 m_size;
};

View File

@@ -20,17 +20,9 @@ namespace Nz
struct SerializationContext
{
Stream* stream;
Endianness endianness;
UInt8 currentBitPos;
UInt8 currentByte;
};
struct UnserializationContext
{
Stream* stream;
Endianness endianness;
UInt8 currentBitPos;
UInt8 currentByte;
Endianness endianness = Endianness_BigEndian; //< Default to Big Endian encoding
UInt8 currentBitPos = 8; //< 8 means no bit is currently wrote
UInt8 currentByte; //< Undefined value, will be initialized at the first bit write
};
}

View File

@@ -1,46 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_SERIALIZER_HPP
#define NAZARA_SERIALIZER_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Serialization.hpp>
namespace Nz
{
class Stream;
class Serializer
{
public:
inline Serializer(Stream& stream);
Serializer(const Serializer&) = default;
Serializer(Serializer&&) = default;
~Serializer();
inline Endianness GetDataEndianness() const;
inline Stream& GetStream() const;
inline bool FlushBits();
inline void SetDataEndianness(Endianness endiannes);
inline void SetStream(Stream& stream);
template<typename T>
Serializer& operator<<(const T& value);
Serializer& operator=(const Serializer&) = default;
Serializer& operator=(Serializer&&) = default;
private:
SerializationContext m_serializationContext;
};
}
#include <Nazara/Core/Serializer.inl>
#endif // NAZARA_SERIALIZER_HPP

View File

@@ -1,67 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
inline Serializer::Serializer(Stream& stream)
{
m_serializationContext.currentBitPos = 8;
m_serializationContext.endianness = Endianness_BigEndian;
m_serializationContext.stream = &stream;
}
inline Serializer::~Serializer()
{
if (!FlushBits())
NazaraWarning("Failed to flush bits at serializer destruction");
}
inline Endianness Serializer::GetDataEndianness() const
{
return m_serializationContext.endianness;
}
inline Stream& Serializer::GetStream() const
{
return *m_serializationContext.stream;
}
inline bool Serializer::FlushBits()
{
if (m_serializationContext.currentBitPos != 8)
{
m_serializationContext.currentBitPos = 8; //< To prevent Serialize to flush bits itself
if (!Serialize<UInt8>(m_serializationContext, m_serializationContext.currentByte))
return false;
}
return true;
}
inline void Serializer::SetDataEndianness(Endianness endiannes)
{
m_serializationContext.endianness = endiannes;
}
inline void Serializer::SetStream(Stream& stream)
{
m_serializationContext.stream = &stream;
}
template<typename T>
Serializer& Serializer::operator<<(const T& value)
{
if (!Serialize(m_serializationContext, value))
NazaraError("Failed to serialize value");
return *this;
}
}
#include <Nazara/Core/DebugOff.hpp>
#include "Serializer.hpp"

View File

@@ -326,7 +326,7 @@ namespace Nz
inline bool HashAppend(AbstractHash* hash, const String& string);
NAZARA_CORE_API bool Serialize(SerializationContext& context, const String& string);
NAZARA_CORE_API bool Unserialize(UnserializationContext& context, String* string);
NAZARA_CORE_API bool Unserialize(SerializationContext& context, String* string);
}
namespace std

View File

@@ -1,44 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_UNSERIALIZER_HPP
#define NAZARA_UNSERIALIZER_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Serialization.hpp>
namespace Nz
{
class Stream;
class Unserializer
{
public:
inline Unserializer(Stream& stream);
Unserializer(const Unserializer&) = default;
Unserializer(Unserializer&&) = default;
~Unserializer() = default;
inline Endianness GetDataEndianness() const;
inline Stream& GetStream() const;
inline void SetDataEndianness(Endianness endiannes);
inline void SetStream(Stream& stream);
template<typename T>
Unserializer& operator>>(T& value);
Unserializer& operator=(const Unserializer&) = default;
Unserializer& operator=(Unserializer&&) = default;
private:
UnserializationContext m_unserializationContext;
};
}
#include <Nazara/Core/Unserializer.inl>
#endif // NAZARA_UNSERIALIZER_HPP

View File

@@ -1,46 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
inline Unserializer::Unserializer(Stream& stream)
{
m_unserializationContext.currentBitPos = 8;
m_unserializationContext.endianness = Endianness_BigEndian;
m_unserializationContext.stream = &stream;
}
inline Endianness Unserializer::GetDataEndianness() const
{
return m_unserializationContext.endianness;
}
inline Stream& Unserializer::GetStream() const
{
return *m_unserializationContext.stream;
}
inline void Unserializer::SetDataEndianness(Endianness endiannes)
{
m_unserializationContext.endianness = endiannes;
}
inline void Unserializer::SetStream(Stream& stream)
{
m_unserializationContext.stream = &stream;
}
template<typename T>
Unserializer& Unserializer::operator>>(T& value)
{
if (!Unserialize(m_unserializationContext, &value))
NazaraError("Failed to serialize value");
return *this;
}
}
#include <Nazara/Core/DebugOff.hpp>