diff --git a/include/Nazara/Core/Algorithm.hpp b/include/Nazara/Core/Algorithm.hpp index 048c5d902..ae30f5065 100644 --- a/include/Nazara/Core/Algorithm.hpp +++ b/include/Nazara/Core/Algorithm.hpp @@ -41,10 +41,10 @@ namespace Nz template std::enable_if_t::value, bool> Serialize(SerializationContext& context, T value); - inline bool Unserialize(UnserializationContext& context, bool* value); + inline bool Unserialize(SerializationContext& context, bool* value); template - std::enable_if_t::value, bool> Unserialize(UnserializationContext& context, T* value); + std::enable_if_t::value, bool> Unserialize(SerializationContext& context, T* value); } #include diff --git a/include/Nazara/Core/Algorithm.inl b/include/Nazara/Core/Algorithm.inl index 5977c6d42..c66bdb046 100644 --- a/include/Nazara/Core/Algorithm.inl +++ b/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 - std::enable_if_t::value, bool> Unserialize(UnserializationContext& context, T* value) + std::enable_if_t::value, bool> Unserialize(SerializationContext& context, T* value) { NazaraAssert(value, "Invalid data pointer"); diff --git a/include/Nazara/Core/ByteStream.hpp b/include/Nazara/Core/ByteStream.hpp new file mode 100644 index 000000000..3b23a9f70 --- /dev/null +++ b/include/Nazara/Core/ByteStream.hpp @@ -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 +#include +#include +#include +#include + +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 + ByteStream& operator>>(T& value); + + template + ByteStream& operator<<(const T& value); + + ByteStream& operator=(const ByteStream&) = delete; + inline ByteStream& operator=(ByteStream&&); + + private: + virtual void OnEmptyStream(); + + std::unique_ptr m_ownedStream; + SerializationContext m_context; + }; +} + +#include + +#endif // NAZARA_BYTESTREAM_HPP diff --git a/include/Nazara/Core/ByteStream.inl b/include/Nazara/Core/ByteStream.inl new file mode 100644 index 000000000..f6e765175 --- /dev/null +++ b/include/Nazara/Core/ByteStream.inl @@ -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 +#include + +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(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 + ByteStream& ByteStream::operator>>(T& value) + { + if (!m_context.stream) + OnEmptyStream(); + + if (!Unserialize(m_context, &value)) + NazaraError("Failed to serialize value"); + + return *this; + } + + template + 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 diff --git a/include/Nazara/Core/MemoryStream.hpp b/include/Nazara/Core/MemoryStream.hpp index 66197c8cc..f5d15fcf0 100644 --- a/include/Nazara/Core/MemoryStream.hpp +++ b/include/Nazara/Core/MemoryStream.hpp @@ -8,16 +8,17 @@ #define NAZARA_MEMORYSTREAM_HPP #include -#include #include 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 diff --git a/include/Nazara/Core/MemoryStream.inl b/include/Nazara/Core/MemoryStream.inl index 61b2f0bb4..73514dcc4 100644 --- a/include/Nazara/Core/MemoryStream.inl +++ b/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 #include 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; } } diff --git a/include/Nazara/Core/MemoryView.hpp b/include/Nazara/Core/MemoryView.hpp index b8a689182..41f4b1ee2 100644 --- a/include/Nazara/Core/MemoryView.hpp +++ b/include/Nazara/Core/MemoryView.hpp @@ -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; }; diff --git a/include/Nazara/Core/Serialization.hpp b/include/Nazara/Core/Serialization.hpp index 409aa6ace..47339b0a2 100644 --- a/include/Nazara/Core/Serialization.hpp +++ b/include/Nazara/Core/Serialization.hpp @@ -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 }; } diff --git a/include/Nazara/Core/Serializer.hpp b/include/Nazara/Core/Serializer.hpp deleted file mode 100644 index ae35f2254..000000000 --- a/include/Nazara/Core/Serializer.hpp +++ /dev/null @@ -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 -#include - -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 - Serializer& operator<<(const T& value); - - Serializer& operator=(const Serializer&) = default; - Serializer& operator=(Serializer&&) = default; - - private: - SerializationContext m_serializationContext; - }; -} - -#include - -#endif // NAZARA_SERIALIZER_HPP diff --git a/include/Nazara/Core/Serializer.inl b/include/Nazara/Core/Serializer.inl deleted file mode 100644 index 69c433ad0..000000000 --- a/include/Nazara/Core/Serializer.inl +++ /dev/null @@ -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 -#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 (!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(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 - Serializer& Serializer::operator<<(const T& value) - { - if (!Serialize(m_serializationContext, value)) - NazaraError("Failed to serialize value"); - - return *this; - } -} - -#include -#include "Serializer.hpp" diff --git a/include/Nazara/Core/String.hpp b/include/Nazara/Core/String.hpp index 7cd26eaf4..a99326bf4 100644 --- a/include/Nazara/Core/String.hpp +++ b/include/Nazara/Core/String.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 diff --git a/include/Nazara/Core/Unserializer.hpp b/include/Nazara/Core/Unserializer.hpp deleted file mode 100644 index 359fc1a7d..000000000 --- a/include/Nazara/Core/Unserializer.hpp +++ /dev/null @@ -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 -#include - -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 - Unserializer& operator>>(T& value); - - Unserializer& operator=(const Unserializer&) = default; - Unserializer& operator=(Unserializer&&) = default; - - private: - UnserializationContext m_unserializationContext; - }; -} - -#include - -#endif // NAZARA_UNSERIALIZER_HPP diff --git a/include/Nazara/Core/Unserializer.inl b/include/Nazara/Core/Unserializer.inl deleted file mode 100644 index 3a832504a..000000000 --- a/include/Nazara/Core/Unserializer.inl +++ /dev/null @@ -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 - -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 - Unserializer& Unserializer::operator>>(T& value) - { - if (!Unserialize(m_unserializationContext, &value)) - NazaraError("Failed to serialize value"); - - return *this; - } -} - -#include diff --git a/src/Nazara/Core/ByteStream.cpp b/src/Nazara/Core/ByteStream.cpp new file mode 100644 index 000000000..175212b48 --- /dev/null +++ b/src/Nazara/Core/ByteStream.cpp @@ -0,0 +1,63 @@ +// 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 +#include +#include +#include +#include +#include + +namespace Nz +{ + ByteStream::ByteStream(ByteArray* byteArray, UInt32 openMode) : + ByteStream() + { + SetStream(byteArray, openMode); + } + + ByteStream::ByteStream(void* ptr, Nz::UInt64 size) : + ByteStream() + { + SetStream(ptr, size); + } + + ByteStream::ByteStream(const void* ptr, Nz::UInt64 size) : + ByteStream() + { + SetStream(ptr, size); + } + + void ByteStream::SetStream(ByteArray* byteArray, UInt32 openMode) + { + std::unique_ptr stream(new MemoryStream(byteArray, openMode)); + + SetStream(m_ownedStream.get()); + // SetStream reset our smart pointer, set it after calling it + m_ownedStream = std::move(stream); + } + + void ByteStream::SetStream(void* ptr, Nz::UInt64 size) + { + std::unique_ptr stream(new MemoryView(ptr, size)); + + SetStream(m_ownedStream.get()); + // SetStream reset our smart pointer, set it after calling it + m_ownedStream = std::move(stream); + } + + void ByteStream::SetStream(const void* ptr, Nz::UInt64 size) + { + std::unique_ptr stream(new MemoryView(ptr, size)); + + SetStream(m_ownedStream.get()); + // SetStream reset our smart pointer, set it after calling it + m_ownedStream = std::move(stream); + } + + void ByteStream::OnEmptyStream() + { + NazaraError("No stream"); + } +} diff --git a/src/Nazara/Core/MemoryStream.cpp b/src/Nazara/Core/MemoryStream.cpp index d141e2b15..b311cd058 100644 --- a/src/Nazara/Core/MemoryStream.cpp +++ b/src/Nazara/Core/MemoryStream.cpp @@ -3,39 +3,22 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include #include #include namespace Nz { - MemoryStream::MemoryStream() : - Stream(StreamOption_None, OpenMode_ReadWrite), - m_pos(0) - { - } - - MemoryStream::MemoryStream(const void* ptr, unsigned int size) : - MemoryStream() - { - m_buffer.Resize(size); - std::memcpy(m_buffer.GetBuffer(), ptr, size); - } - void MemoryStream::Clear() { - m_buffer.Clear(); + m_buffer->Clear(); m_pos = 0; } bool MemoryStream::EndOfStream() const { - return m_pos >= m_buffer.size(); - } - - const ByteArray& MemoryStream::GetBuffer() const - { - return m_buffer; + return m_pos >= m_buffer->size(); } UInt64 MemoryStream::GetCursorPos() const @@ -43,19 +26,20 @@ namespace Nz return m_pos; } - const UInt8* MemoryStream::GetData() const - { - return m_buffer.GetConstBuffer(); - } - UInt64 MemoryStream::GetSize() const { - return m_buffer.size(); + return m_buffer->GetSize(); + } + + void MemoryStream::SetBuffer(ByteArray* byteArray, UInt32 openMode) + { + m_buffer = byteArray; + m_openMode = openMode; } bool MemoryStream::SetCursorPos(UInt64 offset) { - m_pos = std::min(offset, m_buffer.size()); + m_pos = offset; return true; } @@ -67,10 +51,13 @@ namespace Nz std::size_t MemoryStream::ReadBlock(void* buffer, std::size_t size) { - std::size_t readSize = std::min(size, static_cast(m_buffer.size() - m_pos)); + if (EndOfStream()) + return 0; + + std::size_t readSize = std::min(size, static_cast(m_buffer->GetSize() - m_pos)); if (buffer) - std::memcpy(buffer, &m_buffer[m_pos], readSize); + std::memcpy(buffer, m_buffer->GetConstBuffer() + m_pos, readSize); m_pos += readSize; return readSize; @@ -79,10 +66,10 @@ namespace Nz std::size_t MemoryStream::WriteBlock(const void* buffer, std::size_t size) { std::size_t endPos = static_cast(m_pos + size); - if (endPos > m_buffer.size()) - m_buffer.Resize(endPos); + if (endPos > m_buffer->GetSize()) + m_buffer->Resize(endPos); - std::memcpy(&m_buffer[m_pos], buffer, size); + std::memcpy(m_buffer->GetBuffer() + m_pos, buffer, size); m_pos = endPos; return size; diff --git a/src/Nazara/Core/MemoryView.cpp b/src/Nazara/Core/MemoryView.cpp index a630241d5..77c69bcb4 100644 --- a/src/Nazara/Core/MemoryView.cpp +++ b/src/Nazara/Core/MemoryView.cpp @@ -9,9 +9,17 @@ namespace Nz { + MemoryView::MemoryView(void* ptr, UInt64 size) : + Stream(StreamOption_None, OpenMode_ReadWrite), + m_ptr(reinterpret_cast(ptr)), + m_pos(0), + m_size(size) + { + } + MemoryView::MemoryView(const void* ptr, UInt64 size) : Stream(StreamOption_None, OpenMode_ReadOnly), - m_ptr(reinterpret_cast(ptr)), + m_ptr(reinterpret_cast(const_cast(ptr))), //< Okay, right, const_cast is bad, but this pointer is still read-only m_pos(0), m_size(size) { @@ -41,7 +49,7 @@ namespace Nz void MemoryView::FlushStream() { - NazaraInternalError("FlushStream has been called on a MemoryView"); + // Nothing to do } std::size_t MemoryView::ReadBlock(void* buffer, std::size_t size) @@ -57,7 +65,13 @@ namespace Nz std::size_t MemoryView::WriteBlock(const void* buffer, std::size_t size) { - NazaraInternalError("WriteBlock has been called on a MemoryView"); - return 0; + std::size_t endPos = static_cast(m_pos + size); + if (endPos > m_size) + size = m_size - m_pos; + + std::memcpy(&m_ptr[m_pos], buffer, size); + + m_pos += size; + return size; } } diff --git a/src/Nazara/Core/String.cpp b/src/Nazara/Core/String.cpp index 76aa7510e..daa5cb85a 100644 --- a/src/Nazara/Core/String.cpp +++ b/src/Nazara/Core/String.cpp @@ -4226,7 +4226,7 @@ namespace Nz return context.stream->Write(string.GetConstBuffer(), string.GetSize()) == string.GetSize(); } - bool Unserialize(UnserializationContext& context, String* string) + bool Unserialize(SerializationContext& context, String* string) { UInt32 size; if (!Unserialize(context, &size))