diff --git a/ChangeLog.md b/ChangeLog.md index e87ec785e..829e42437 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -221,6 +221,7 @@ Nazara Engine: - ⚠ TextDrawers now use floating-point internally and to exposes their Bounds (AbstractTextDrawer::GetBounds() now returns a Rectf) - Added [SimpleTextDrawer|RichTextDrawer] character and line spacing offset properties - Added ENetHost::AllowsIncomingConnections(bool) to disable/re-enable server peers connection +- Added ByteArrayPool and PoolByteStream classes Nazara Development Kit: - Added ImageWidget (#139) diff --git a/include/Nazara/Core/ByteArrayPool.hpp b/include/Nazara/Core/ByteArrayPool.hpp new file mode 100644 index 000000000..e45ceee67 --- /dev/null +++ b/include/Nazara/Core/ByteArrayPool.hpp @@ -0,0 +1,43 @@ +// Copyright (C) 2017 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_BYTEARRAYPOOL_HPP +#define NAZARA_BYTEARRAYPOOL_HPP + +#include +#include +#include +#include + +namespace Nz +{ + class AbstractHash; + + class NAZARA_CORE_API ByteArrayPool + { + public: + ByteArrayPool() = default; + ByteArrayPool(const ByteArrayPool&) = delete; + ByteArrayPool(ByteArrayPool&&) = default; + ~ByteArrayPool() = default; + + inline void Clear(); + + inline ByteArray GetByteArray(std::size_t capacity = 0); + + inline void ReturnByteArray(ByteArray byteArray); + + ByteArrayPool& operator=(const ByteArrayPool&) = delete; + ByteArrayPool& operator=(ByteArrayPool&&) = default; + + private: + std::vector m_byteArrays; + }; +} + +#include + +#endif // NAZARA_BYTEARRAYPOOL_HPP diff --git a/include/Nazara/Core/ByteArrayPool.inl b/include/Nazara/Core/ByteArrayPool.inl new file mode 100644 index 000000000..82cf8349c --- /dev/null +++ b/include/Nazara/Core/ByteArrayPool.inl @@ -0,0 +1,44 @@ +// Copyright (C) 2017 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 +{ + namespace Detail + { + bool SortByteArrayByCapacity(const ByteArray& byteArray, std::size_t refCapacity) + { + return refCapacity > byteArray.GetCapacity(); + } + } + + inline void ByteArrayPool::Clear() + { + m_byteArrays.clear(); + } + + inline ByteArray ByteArrayPool::GetByteArray(std::size_t capacity) + { + ByteArray ret; + + auto it = std::lower_bound(m_byteArrays.begin(), m_byteArrays.end(), capacity, Detail::SortByteArrayByCapacity); + if (it != m_byteArrays.end()) + { + ret = std::move(*it); + m_byteArrays.erase(it); + } + + return ret; + } + + inline void ByteArrayPool::ReturnByteArray(ByteArray byteArray) + { + auto it = std::lower_bound(m_byteArrays.begin(), m_byteArrays.end(), byteArray.GetCapacity(), Detail::SortByteArrayByCapacity); + m_byteArrays.emplace(it, std::move(byteArray)); + } +} + +#include diff --git a/include/Nazara/Core/PoolByteStream.hpp b/include/Nazara/Core/PoolByteStream.hpp new file mode 100644 index 000000000..63150290d --- /dev/null +++ b/include/Nazara/Core/PoolByteStream.hpp @@ -0,0 +1,46 @@ +// Copyright (C) 2017 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_POOLBYTESTREAM_HPP +#define NAZARA_POOLBYTESTREAM_HPP + +#include +#include +#include +#include + +namespace Nz +{ + class ByteArrayPool; + + class NAZARA_CORE_API PoolByteStream : public ByteStream + { + friend class Network; + + public: + inline PoolByteStream(ByteArrayPool& pool); + inline PoolByteStream(ByteArrayPool& pool, std::size_t capacity); + PoolByteStream(const PoolByteStream&) = delete; + PoolByteStream(PoolByteStream&& packet) = default; + inline ~PoolByteStream(); + + void Reset(); + void Reset(std::size_t capacity); + + PoolByteStream& operator=(const PoolByteStream&) = delete; + PoolByteStream& operator=(PoolByteStream&&) = delete; + + private: + void OnEmptyStream() override; + + ByteArrayPool& m_pool; + ByteArray m_buffer; + }; +} + +#include + +#endif // NAZARA_POOLBYTESTREAM_HPP diff --git a/include/Nazara/Core/PoolByteStream.inl b/include/Nazara/Core/PoolByteStream.inl new file mode 100644 index 000000000..d786c6a67 --- /dev/null +++ b/include/Nazara/Core/PoolByteStream.inl @@ -0,0 +1,30 @@ +// Copyright (C) 2017 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 + +namespace Nz +{ + inline PoolByteStream::PoolByteStream(ByteArrayPool& pool) : + m_pool(pool) + { + } + + inline PoolByteStream::PoolByteStream(ByteArrayPool& pool, std::size_t capacity) : + PoolByteStream(pool) + { + Reset(capacity); + } + + inline PoolByteStream::~PoolByteStream() + { + FlushBits(); //< Needs to be done here as the stream will be freed before ByteStream calls it + Reset(); //< Returns the byte array (if any) to the pool + } +} + +#include diff --git a/src/Nazara/Core/ByteStream.cpp b/src/Nazara/Core/ByteStream.cpp index a61cae520..6559e50fb 100644 --- a/src/Nazara/Core/ByteStream.cpp +++ b/src/Nazara/Core/ByteStream.cpp @@ -68,7 +68,7 @@ namespace Nz void ByteStream::SetStream(ByteArray* byteArray, OpenModeFlags openMode) { - std::unique_ptr stream(new MemoryStream(byteArray, openMode)); + std::unique_ptr stream = std::make_unique(byteArray, openMode); SetStream(stream.get()); // SetStream reset our smart pointer, set it after calling it @@ -86,7 +86,7 @@ namespace Nz void ByteStream::SetStream(void* ptr, Nz::UInt64 size) { - std::unique_ptr stream(new MemoryView(ptr, size)); + std::unique_ptr stream = std::make_unique(ptr, size); SetStream(stream.get()); // SetStream reset our smart pointer, set it after calling it @@ -104,7 +104,7 @@ namespace Nz void ByteStream::SetStream(const void* ptr, Nz::UInt64 size) { - std::unique_ptr stream(new MemoryView(ptr, size)); + std::unique_ptr stream = std::make_unique(ptr, size); SetStream(stream.get()); // SetStream reset our smart pointer, set it after calling it diff --git a/src/Nazara/Core/PoolByteStream.cpp b/src/Nazara/Core/PoolByteStream.cpp new file mode 100644 index 000000000..889fe32ca --- /dev/null +++ b/src/Nazara/Core/PoolByteStream.cpp @@ -0,0 +1,40 @@ +// Copyright (C) 2017 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 + +namespace Nz +{ + /*! + * \ingroup core + * \class Nz::PoolByteStream + * \brief ByteStream allocated using a pool + */ + + void PoolByteStream::Reset() + { + if (m_buffer.GetCapacity() > 0) + { + m_pool.ReturnByteArray(std::move(m_buffer)); + m_buffer.Clear(false); + } + + SetStream(static_cast(nullptr)); + } + + void PoolByteStream::Reset(std::size_t capacity) + { + if (m_buffer.GetCapacity() < capacity) + m_buffer = m_pool.GetByteArray(capacity); + + SetStream(&m_buffer, Nz::OpenMode_ReadWrite); + } + + void PoolByteStream::OnEmptyStream() + { + Reset(0); + } +}