Add stream buffering (WIP)

This commit is contained in:
SirLynix
2022-04-09 18:22:57 +02:00
parent 2b66ea1e90
commit 22f58fdbf5
14 changed files with 291 additions and 189 deletions

View File

@@ -32,15 +32,6 @@ namespace Nz
return false;
}
/*!
* \brief Gets the position of the cursor (which is always zero)
* \return Always zero
*/
UInt64 EmptyStream::GetCursorPos() const
{
return 0;
}
/*!
* \brief Gets the size of the raw memory (how many bytes would have been written on a regular stream)
* \return Size occupied until now
@@ -50,17 +41,6 @@ namespace Nz
return m_size;
}
/*!
* \brief Does nothing
* \return true
*
* \param offset Offset according to the beginning of the stream
*/
bool EmptyStream::SetCursorPos(UInt64 /*offset*/)
{
return true;
}
/*!
* \brief Flushes the stream (does nothing)
*/
@@ -83,6 +63,26 @@ namespace Nz
return 0;
}
/*!
* \brief Does nothing
* \return true
*
* \param offset Offset according to the beginning of the stream
*/
bool EmptyStream::SeekStreamCursor(UInt64 /*offset*/)
{
return true;
}
/*!
* \brief Gets the position of the cursor (which is always zero)
* \return Always zero
*/
UInt64 EmptyStream::TellStreamCursor() const
{
return 0;
}
/*!
* \brief Writes data
* \return size

View File

@@ -154,20 +154,6 @@ namespace Nz
return std::filesystem::exists(m_filePath);
}
/*!
* \brief Gets the position of the cursor in the file
* \return Position of the cursor
*
* \remark Produces a NazaraAssert if file is not open
*/
UInt64 File::GetCursorPos() const
{
NazaraAssert(IsOpen(), "File is not open");
return m_impl->GetCursorPos();
}
/*!
* \brief Gets the directory of the file
* \return Directory of the file
@@ -240,6 +226,8 @@ namespace Nz
m_openMode = openMode;
m_impl = std::move(impl);
EnableBuffering(!m_openMode.Test(OpenMode::Unbuffered));
if (m_openMode & OpenMode::Text)
m_streamOptions |= StreamOption::Text;
else
@@ -266,39 +254,6 @@ namespace Nz
return Open(openMode);
}
/*!
* \brief Sets the position of the cursor
* \return true if cursor is successfully positioned
*
* \param pos Position of the cursor
* \param offset Offset according to the cursor position
*
* \remark Produces a NazaraAssert if file is not open
*/
bool File::SetCursorPos(CursorPosition pos, Int64 offset)
{
NazaraAssert(IsOpen(), "File is not open");
return m_impl->SetCursorPos(pos, offset);
}
/*!
* \brief Sets the position of the cursor
* \return true if cursor is successfully positioned
*
* \param offset Offset according to the cursor begin position
*
* \remark Produces a NazaraAssert if file is not open
*/
bool File::SetCursorPos(UInt64 offset)
{
NazaraAssert(IsOpen(), "File is not open");
return m_impl->SetCursorPos(CursorPosition::AtBegin, offset);
}
/*!
* \brief Sets the file path
* \return true if file opening is successful
@@ -389,6 +344,35 @@ namespace Nz
}
}
/*!
* \brief Sets the position of the cursor
* \return true if cursor is successfully positioned
*
* \param offset Offset according to the cursor begin position
*
* \remark Produces a NazaraAssert if file is not open
*/
bool File::SeekStreamCursor(UInt64 offset)
{
NazaraAssert(IsOpen(), "File is not open");
return m_impl->SetCursorPos(CursorPosition::AtBegin, offset);
}
/*!
* \brief Gets the position of the cursor in the file
* \return Position of the cursor
*
* \remark Produces a NazaraAssert if file is not open
*/
UInt64 File::TellStreamCursor() const
{
NazaraAssert(IsOpen(), "File is not open");
return m_impl->GetCursorPos();
}
/*!
* \brief Writes blocks
* \return Number of blocks written

View File

@@ -36,16 +36,6 @@ namespace Nz
return m_pos >= m_buffer->size();
}
/*!
* \brief Gets the position of the cursor
* \return Position of the cursor
*/
UInt64 MemoryStream::GetCursorPos() const
{
return m_pos;
}
/*!
* \brief Gets the size of the raw memory
* \return Size of the memory
@@ -73,20 +63,6 @@ namespace Nz
m_openMode = openMode;
}
/*!
* \brief Sets the position of the cursor
* \return true
*
* \param offset Offset according to the beginning of the stream
*/
bool MemoryStream::SetCursorPos(UInt64 offset)
{
m_pos = offset;
return true;
}
/*!
* \brief Flushes the stream
*/
@@ -118,6 +94,28 @@ namespace Nz
return readSize;
}
/*!
* \brief Sets the position of the cursor
* \return true
*
* \param offset Offset according to the beginning of the stream
*/
bool MemoryStream::SeekStreamCursor(UInt64 offset)
{
m_pos = offset;
return true;
}
/*!
* \brief Gets the position of the cursor
* \return Position of the cursor
*/
UInt64 MemoryStream::TellStreamCursor() const
{
return m_pos;
}
/*!
* \brief Writes blocks
* \return Number of blocks written
@@ -127,7 +125,6 @@ namespace Nz
*
* \remark Produces a NazaraAssert if buffer is nullptr
*/
std::size_t MemoryStream::WriteBlock(const void* buffer, std::size_t size)
{
if (size > 0)

View File

@@ -59,16 +59,6 @@ namespace Nz
return m_pos >= m_size;
}
/*!
* \brief Gets the position of the cursor
* \return Position of the cursor
*/
UInt64 MemoryView::GetCursorPos() const
{
return m_pos;
}
/*!
* \brief Gets the size of the raw memory
* \return Size of the memory
@@ -79,20 +69,6 @@ namespace Nz
return m_size;
}
/*!
* \brief Sets the position of the cursor
* \return true
*
* \param offset Offset according to the beginning of the stream
*/
bool MemoryView::SetCursorPos(UInt64 offset)
{
m_pos = std::min(offset, m_size);
return true;
}
/*!
* \brief Flushes the stream
*/
@@ -121,6 +97,28 @@ namespace Nz
return readSize;
}
/*!
* \brief Sets the position of the cursor
* \return true
*
* \param offset Offset according to the beginning of the stream
*/
bool MemoryView::SeekStreamCursor(UInt64 offset)
{
m_pos = std::min(offset, m_size);
return true;
}
/*!
* \brief Gets the position of the cursor
* \return Position of the cursor
*/
UInt64 MemoryView::TellStreamCursor() const
{
return m_pos;
}
/*!
* \brief Writes blocks
* \return Number of blocks written

View File

@@ -30,7 +30,7 @@ namespace Nz
std::filesystem::path Stream::GetDirectory() const
{
return std::filesystem::path();
return {};
}
/*!
@@ -40,7 +40,81 @@ namespace Nz
std::filesystem::path Stream::GetPath() const
{
return std::filesystem::path();
return {};
}
UInt64 Stream::GetCursorPos() const
{
if (m_bufferCapacity == 0)
return TellStreamCursor();
else
{
assert(m_bufferCursor >= m_bufferSize);
return m_bufferCursor - m_bufferSize + m_bufferOffset;
}
}
/*!
* \brief Reads the stream and puts the result in a buffer
* \return Size of the read
*
* \param buffer Buffer to stock data
* \param size Size meant to be read
*
* \remark Produces a NazaraAssert if stream is not readable
* \remark If preallocated space of buffer is less than the size, the behavior is undefined
*/
std::size_t Stream::Read(void* buffer, std::size_t size)
{
NazaraAssert(IsReadable(), "Stream is not readable");
if (m_bufferCapacity == 0)
return ReadBlock(buffer, size);
UInt8* ptr = static_cast<UInt8*>(buffer);
std::size_t readSize = 0;
if (m_bufferOffset < m_bufferSize)
{
std::size_t availableSize = std::min(size, m_bufferSize - m_bufferOffset);
if (ptr)
{
std::memcpy(ptr, &m_buffer[m_bufferOffset], availableSize);
ptr += availableSize;
}
m_bufferOffset += availableSize;
readSize += availableSize;
size -= availableSize;
}
if (size > m_bufferCapacity)
{
// Unbuffered read
m_bufferSize = 0;
std::size_t blockSize = ReadBlock(ptr, size);
m_bufferCursor += blockSize;
readSize += blockSize;
}
else if (size > 0)
{
m_bufferOffset = 0;
m_bufferSize = ReadBlock(&m_buffer[0], m_bufferCapacity);
m_bufferCursor += m_bufferSize;
std::size_t remainingSize = std::min(m_bufferSize, size);
if (ptr)
{
std::memcpy(ptr, &m_buffer[m_bufferOffset], remainingSize);
ptr += remainingSize;
}
m_bufferOffset += remainingSize;
readSize += remainingSize;
size -= remainingSize;
}
return readSize;
}
/*!

View File

@@ -147,19 +147,6 @@ namespace Nz
return QueryAvailableBytes() == 0;
}
/*!
* \brief Gets the position of the cursor
* \return 0
*
* \remark Produces a NazaraError because it is a special stream
*/
UInt64 TcpClient::GetCursorPos() const
{
NazaraError("GetCursorPos() cannot be used on sequential streams");
return 0;
}
/*!
* \brief Gets the size of the raw memory available
* \return Size of the memory available
@@ -456,21 +443,6 @@ namespace Nz
return Send(ptr, size, nullptr);
}
/*!
* \brief Sets the position of the cursor
* \return false
*
* \param offset Offset according to the beginning of the stream
*
* \remark Produces a NazaraError because it is a special stream
*/
bool TcpClient::SetCursorPos(UInt64 /*offset*/)
{
NazaraError("SetCursorPos() cannot be used on sequential streams");
return false;
}
/*!
* \brief Waits for being connected before time out
* \return The new socket state, either Connected if connection did succeed or NotConnected if an error occurred
@@ -605,6 +577,32 @@ namespace Nz
UpdateState(SocketState::Connected);
}
/*!
* \brief Sets the position of the cursor
* \return false
*
* \param offset Offset according to the beginning of the stream
*
* \remark Produces a NazaraError because it is a special stream
*/
bool TcpClient::SeekStreamCursor(UInt64 /*offset*/)
{
NazaraError("SeekStreamCursor() cannot be used on sequential streams");
return false;
}
/*!
* \brief Gets the position of the cursor
* \return 0
*
* \remark Produces a NazaraError because it is a special stream
*/
UInt64 TcpClient::TellStreamCursor() const
{
NazaraError("TellStreamCursor() cannot be used on sequential streams");
return 0;
}
/*!
* \brief Writes blocks
* \return Number of blocks written