Core: Rework Serialization
Former-commit-id: d97eedbd3efc92235e3880ad061a5216fa77ebd7
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
65
include/Nazara/Core/ByteStream.hpp
Normal file
65
include/Nazara/Core/ByteStream.hpp
Normal 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
|
||||
129
include/Nazara/Core/ByteStream.inl
Normal file
129
include/Nazara/Core/ByteStream.inl
Normal 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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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"
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user