From 138f2b88b35428d480b8f8a2b30b7afdb2b2c263 Mon Sep 17 00:00:00 2001 From: SirLynix Date: Tue, 19 Apr 2022 13:38:44 +0200 Subject: [PATCH] Fix buffering issues --- include/Nazara/Core/EmptyStream.hpp | 3 +- include/Nazara/Core/File.hpp | 4 +-- include/Nazara/Core/MemoryStream.hpp | 3 +- include/Nazara/Core/MemoryView.hpp | 3 +- include/Nazara/Core/Stream.hpp | 3 +- include/Nazara/Core/Stream.inl | 24 +------------ include/Nazara/Network/TcpClient.hpp | 3 +- src/Nazara/Core/EmptyStream.cpp | 18 +++++----- src/Nazara/Core/File.cpp | 50 +++++++++------------------- src/Nazara/Core/MemoryStream.cpp | 21 ++++++------ src/Nazara/Core/MemoryView.cpp | 19 +++++------ src/Nazara/Core/Stream.cpp | 36 ++++++++++++++++++++ src/Nazara/Network/TcpClient.cpp | 20 +++++------ tests/Engine/Core/BufferingTest.cpp | 4 ++- 14 files changed, 99 insertions(+), 112 deletions(-) diff --git a/include/Nazara/Core/EmptyStream.hpp b/include/Nazara/Core/EmptyStream.hpp index 6226c5440..c2d7c734e 100644 --- a/include/Nazara/Core/EmptyStream.hpp +++ b/include/Nazara/Core/EmptyStream.hpp @@ -22,8 +22,6 @@ namespace Nz void Clear(); - bool EndOfStream() const override; - UInt64 GetSize() const override; EmptyStream& operator=(const EmptyStream&) = default; @@ -34,6 +32,7 @@ namespace Nz std::size_t ReadBlock(void* buffer, std::size_t size) override; bool SeekStreamCursor(UInt64 offset) override; UInt64 TellStreamCursor() const override; + bool TestStreamEnd() const override; std::size_t WriteBlock(const void* buffer, std::size_t size) override; UInt64 m_size; diff --git a/include/Nazara/Core/File.hpp b/include/Nazara/Core/File.hpp index fb2e35764..a487eed4a 100644 --- a/include/Nazara/Core/File.hpp +++ b/include/Nazara/Core/File.hpp @@ -35,9 +35,6 @@ namespace Nz bool Delete(); - bool EndOfFile() const; - bool EndOfStream() const override; - bool Exists() const; std::filesystem::path GetDirectory() const override; @@ -64,6 +61,7 @@ namespace Nz std::size_t ReadBlock(void* buffer, std::size_t size) override; bool SeekStreamCursor(UInt64 offset) override; UInt64 TellStreamCursor() const override; + bool TestStreamEnd() const override; std::size_t WriteBlock(const void* buffer, std::size_t size) override; std::filesystem::path m_filePath; diff --git a/include/Nazara/Core/MemoryStream.hpp b/include/Nazara/Core/MemoryStream.hpp index e02b2d574..0543dc920 100644 --- a/include/Nazara/Core/MemoryStream.hpp +++ b/include/Nazara/Core/MemoryStream.hpp @@ -26,8 +26,6 @@ namespace Nz void Clear(); - bool EndOfStream() const override; - inline ByteArray& GetBuffer(); inline const ByteArray& GetBuffer() const; UInt64 GetSize() const override; @@ -42,6 +40,7 @@ namespace Nz std::size_t ReadBlock(void* buffer, std::size_t size) override; bool SeekStreamCursor(UInt64 offset) override; UInt64 TellStreamCursor() const override; + bool TestStreamEnd() const override; std::size_t WriteBlock(const void* buffer, std::size_t size) override; MovablePtr m_buffer; diff --git a/include/Nazara/Core/MemoryView.hpp b/include/Nazara/Core/MemoryView.hpp index 7466f8708..ca5545e3a 100644 --- a/include/Nazara/Core/MemoryView.hpp +++ b/include/Nazara/Core/MemoryView.hpp @@ -21,8 +21,6 @@ namespace Nz MemoryView(MemoryView&&) = delete; ///TODO ~MemoryView() = default; - bool EndOfStream() const override; - UInt64 GetSize() const override; MemoryView& operator=(const MemoryView&) = delete; @@ -33,6 +31,7 @@ namespace Nz std::size_t ReadBlock(void* buffer, std::size_t size) override; bool SeekStreamCursor(UInt64 offset) override; UInt64 TellStreamCursor() const override; + bool TestStreamEnd() const override; std::size_t WriteBlock(const void* buffer, std::size_t size) override; UInt8* m_ptr; diff --git a/include/Nazara/Core/Stream.hpp b/include/Nazara/Core/Stream.hpp index 39e4167e3..e17e6b2b6 100644 --- a/include/Nazara/Core/Stream.hpp +++ b/include/Nazara/Core/Stream.hpp @@ -25,7 +25,7 @@ namespace Nz Stream(Stream&&) noexcept = default; virtual ~Stream(); - virtual bool EndOfStream() const = 0; + bool EndOfStream() const; inline void EnableBuffering(bool buffering, std::size_t bufferSize = DefaultBufferSize); inline void EnableTextMode(bool textMode); @@ -67,6 +67,7 @@ namespace Nz virtual std::size_t ReadBlock(void* buffer, std::size_t size) = 0; virtual bool SeekStreamCursor(UInt64 offset) = 0; virtual UInt64 TellStreamCursor() const = 0; + virtual bool TestStreamEnd() const = 0; virtual std::size_t WriteBlock(const void* buffer, std::size_t size) = 0; std::size_t m_bufferCapacity; diff --git a/include/Nazara/Core/Stream.inl b/include/Nazara/Core/Stream.inl index 03c03b646..1a6d7e0ac 100644 --- a/include/Nazara/Core/Stream.inl +++ b/include/Nazara/Core/Stream.inl @@ -4,6 +4,7 @@ #include #include +#include #include namespace Nz @@ -140,29 +141,6 @@ namespace Nz return (m_openMode & OpenMode::WriteOnly) != 0; } - inline bool Stream::SetCursorPos(UInt64 offset) - { - if (m_bufferCapacity == 0) - return SeekStreamCursor(offset); - else - { - if (offset >= m_bufferCursor && offset - m_bufferCursor < m_bufferSize) - m_bufferOffset += offset - m_bufferCursor; - else - { - // Out of buffer - if (!SeekStreamCursor(offset)) - return false; - - m_bufferCursor = offset; - m_bufferOffset = 0; - m_bufferSize = 0; - } - - return true; - } - } - /*! * \brief Writes in the stream the content of a buffer * \return Size of the writing diff --git a/include/Nazara/Network/TcpClient.hpp b/include/Nazara/Network/TcpClient.hpp index 7ac73f6d2..2689a765c 100644 --- a/include/Nazara/Network/TcpClient.hpp +++ b/include/Nazara/Network/TcpClient.hpp @@ -35,8 +35,6 @@ namespace Nz void EnableLowDelay(bool lowDelay); void EnableKeepAlive(bool keepAlive, UInt64 msTime = 10000, UInt64 msInterval = 1000); - bool EndOfStream() const override; - inline UInt64 GetKeepAliveInterval() const; inline UInt64 GetKeepAliveTime() const; inline IpAddress GetRemoteAddress() const; @@ -68,6 +66,7 @@ namespace Nz void Reset(SocketHandle handle, const IpAddress& peerAddress); bool SeekStreamCursor(UInt64 offset) override; UInt64 TellStreamCursor() const override; + bool TestStreamEnd() const override; std::size_t WriteBlock(const void* buffer, std::size_t size) override; struct PendingPacket diff --git a/src/Nazara/Core/EmptyStream.cpp b/src/Nazara/Core/EmptyStream.cpp index 853436f88..6db0e10ae 100644 --- a/src/Nazara/Core/EmptyStream.cpp +++ b/src/Nazara/Core/EmptyStream.cpp @@ -23,15 +23,6 @@ namespace Nz m_size = 0; } - /*! - * \brief Checks whether the stream reached the end of the stream - * \return Always false - */ - bool EmptyStream::EndOfStream() const - { - return false; - } - /*! * \brief Gets the size of the raw memory (how many bytes would have been written on a regular stream) * \return Size occupied until now @@ -83,6 +74,15 @@ namespace Nz return 0; } + /*! + * \brief Checks whether the stream reached the end of the stream + * \return Always false + */ + bool EmptyStream::TestStreamEnd() const + { + return false; + } + /*! * \brief Writes data * \return size diff --git a/src/Nazara/Core/File.cpp b/src/Nazara/Core/File.cpp index 0b6a108de..c009aff8b 100644 --- a/src/Nazara/Core/File.cpp +++ b/src/Nazara/Core/File.cpp @@ -107,40 +107,6 @@ namespace Nz return std::filesystem::remove(m_filePath); } - /*! - * \brief Checks whether the file has reached the end - * \return true if cursor is at the end of the file - * - * \remark Produces a NazaraError if file is not open with NAZARA_CORE_SAFE defined - */ - - bool File::EndOfFile() const - { - #if NAZARA_CORE_SAFE - if (!IsOpen()) - { - NazaraError("File not open"); - return false; - } - #endif - - return m_impl->EndOfFile(); - } - - /*! - * \brief Checks whether the file has reached the end of the stream - * \return true if cursor is at the end of the file - * - * \remark Produces a NazaraError if file is not open with NAZARA_CORE_SAFE defined - * - * \see EndOfFile - */ - - bool File::EndOfStream() const - { - return EndOfFile(); - } - /*! * \brief Checks whether the file exists * \return true if file exists @@ -373,6 +339,21 @@ namespace Nz return m_impl->GetCursorPos(); } + /*! + * \brief Checks whether the file has reached the end of the stream + * \return true if cursor is at the end of the file + * + * \remark Produces a NazaraError if file is not open with NAZARA_CORE_SAFE defined + * + * \see EndOfFile + */ + bool File::TestStreamEnd() const + { + NazaraAssert(IsOpen(), "File is not open"); + + return m_impl->EndOfFile(); + } + /*! * \brief Writes blocks * \return Number of blocks written @@ -383,7 +364,6 @@ namespace Nz * \remark Produces a NazaraAssert if file is not open * \remark Produces a NazaraAssert if buffer is nullptr */ - std::size_t File::WriteBlock(const void* buffer, std::size_t size) { NazaraAssert(IsOpen(), "File is not open"); diff --git a/src/Nazara/Core/MemoryStream.cpp b/src/Nazara/Core/MemoryStream.cpp index cd0c5550e..6611a04f3 100644 --- a/src/Nazara/Core/MemoryStream.cpp +++ b/src/Nazara/Core/MemoryStream.cpp @@ -26,16 +26,6 @@ namespace Nz m_pos = 0; } - /*! - * \brief Checks whether the stream reached the end of the stream - * \return true if cursor is at the end of the stream - */ - - bool MemoryStream::EndOfStream() const - { - return m_pos >= m_buffer->size(); - } - /*! * \brief Gets the size of the raw memory * \return Size of the memory @@ -82,7 +72,7 @@ namespace Nz std::size_t MemoryStream::ReadBlock(void* buffer, std::size_t size) { - if (EndOfStream()) + if (TestStreamEnd()) return 0; std::size_t readSize = std::min(size, static_cast(m_buffer->GetSize() - m_pos)); @@ -116,6 +106,15 @@ namespace Nz return m_pos; } + /*! + * \brief Checks whether the stream reached the end of the stream + * \return true if cursor is at the end of the stream + */ + bool MemoryStream::TestStreamEnd() const + { + return m_pos >= m_buffer->size(); + } + /*! * \brief Writes blocks * \return Number of blocks written diff --git a/src/Nazara/Core/MemoryView.cpp b/src/Nazara/Core/MemoryView.cpp index bb805d8ab..1f9017d89 100644 --- a/src/Nazara/Core/MemoryView.cpp +++ b/src/Nazara/Core/MemoryView.cpp @@ -49,16 +49,6 @@ namespace Nz { } - /*! - * \brief Checks whether the stream reached the end of the stream - * \return true if cursor is at the end of the stream - */ - - bool MemoryView::EndOfStream() const - { - return m_pos >= m_size; - } - /*! * \brief Gets the size of the raw memory * \return Size of the memory @@ -119,6 +109,15 @@ namespace Nz return m_pos; } + /*! + * \brief Checks whether the stream reached the end of the stream + * \return true if cursor is at the end of the stream + */ + bool MemoryView::TestStreamEnd() const + { + return m_pos >= m_size; + } + /*! * \brief Writes blocks * \return Number of blocks written diff --git a/src/Nazara/Core/Stream.cpp b/src/Nazara/Core/Stream.cpp index 46fbb19e1..71803c6b4 100644 --- a/src/Nazara/Core/Stream.cpp +++ b/src/Nazara/Core/Stream.cpp @@ -23,6 +23,17 @@ namespace Nz Stream::~Stream() = default; + bool Stream::EndOfStream() const + { + if (m_bufferCapacity > 0) + { + if (m_bufferOffset < m_bufferSize) + return false; + } + + return TestStreamEnd(); + } + /*! * \brief Gets the directory of the stream * \return Empty string (meant to be virtual) @@ -91,6 +102,7 @@ namespace Nz if (size > m_bufferCapacity) { // Unbuffered read + m_bufferOffset = 0; m_bufferSize = 0; std::size_t blockSize = ReadBlock(ptr, size); m_bufferCursor += blockSize; @@ -201,6 +213,30 @@ namespace Nz return line; } + bool Stream::SetCursorPos(UInt64 offset) + { + if (m_bufferCapacity == 0) + return SeekStreamCursor(offset); + else + { + assert(m_bufferCursor >= m_bufferSize); + if (offset < m_bufferCursor && offset >= m_bufferCursor - m_bufferSize) + m_bufferOffset = offset - (m_bufferCursor - m_bufferSize); + else + { + // Out of buffer + if (!SeekStreamCursor(offset)) + return false; + + m_bufferCursor = offset; + m_bufferOffset = 0; + m_bufferSize = 0; + } + + return true; + } + } + /*! * \brief Writes a ByteArray into the stream * \return true if successful diff --git a/src/Nazara/Network/TcpClient.cpp b/src/Nazara/Network/TcpClient.cpp index cca156253..455f14238 100644 --- a/src/Nazara/Network/TcpClient.cpp +++ b/src/Nazara/Network/TcpClient.cpp @@ -137,16 +137,6 @@ namespace Nz } } - /*! - * \brief Checks whether the stream reached the end of the stream - * \return true if there is no more available bytes - */ - - bool TcpClient::EndOfStream() const - { - return QueryAvailableBytes() == 0; - } - /*! * \brief Gets the size of the raw memory available * \return Size of the memory available @@ -603,6 +593,15 @@ namespace Nz return 0; } + /*! + * \brief Checks whether the stream reached the end of the stream + * \return true if there is no more available bytes + */ + bool TcpClient::TestStreamEnd() const + { + return QueryAvailableBytes() == 0; + } + /*! * \brief Writes blocks * \return Number of blocks written @@ -613,7 +612,6 @@ namespace Nz * \remark Produces a NazaraAssert if buffer is nullptr * \remark Produces a NazaraAssert if socket is invalid */ - std::size_t TcpClient::WriteBlock(const void* buffer, std::size_t size) { NazaraAssert(buffer, "Invalid buffer"); diff --git a/tests/Engine/Core/BufferingTest.cpp b/tests/Engine/Core/BufferingTest.cpp index dcb72b734..ef59445e2 100644 --- a/tests/Engine/Core/BufferingTest.cpp +++ b/tests/Engine/Core/BufferingTest.cpp @@ -5,7 +5,7 @@ SCENARIO("Buffering", "[CORE][BUFFERING]") { const char mem[] = "abcdefghijklmnopqrstuvwxyz"; - for (std::size_t bufferSize : { 1, 2, 3, 4, 7, 0xFFFF }) + for (std::size_t bufferSize : { 1, 2, 3, 4, 6, 7, 0xFFFF }) { Nz::MemoryView memView(mem, sizeof(mem)); memView.EnableBuffering(true, bufferSize); @@ -45,6 +45,7 @@ SCENARIO("Buffering", "[CORE][BUFFERING]") AND_WHEN("Seeking at 10") { memView.SetCursorPos(10); + CHECK(memView.GetCursorPos() == 10); readBuffer.resize(2); REQUIRE(memView.Read(readBuffer.data(), readBuffer.size()) == readBuffer.size()); @@ -55,6 +56,7 @@ SCENARIO("Buffering", "[CORE][BUFFERING]") AND_WHEN("Seeking at 6 and reading") { memView.SetCursorPos(6); + CHECK(memView.GetCursorPos() == 6); readBuffer.resize(2); REQUIRE(memView.Read(readBuffer.data(), readBuffer.size()) == readBuffer.size());