mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-23 23:04:36 +01:00
Refactor Compression and Streams, and Add IStream Direct Interface
This commit is contained in:
161
src/openrct2/core/StreamBuffer.cpp
Normal file
161
src/openrct2/core/StreamBuffer.cpp
Normal file
@@ -0,0 +1,161 @@
|
||||
/*****************************************************************************
|
||||
* Copyright (c) 2014-2025 OpenRCT2 developers
|
||||
*
|
||||
* For a complete list of all authors, please refer to contributors.md
|
||||
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
||||
*
|
||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "StreamBuffer.hpp"
|
||||
|
||||
#include "Guard.hpp"
|
||||
#include "Memory.hpp"
|
||||
|
||||
namespace OpenRCT2
|
||||
{
|
||||
StreamReadBuffer::StreamReadBuffer(IStream& stream, uint64_t length, size_t bufferLength)
|
||||
{
|
||||
OpenRCT2::Guard::Assert(bufferLength > 0);
|
||||
|
||||
_remaining = length;
|
||||
if (length <= std::numeric_limits<size_t>::max())
|
||||
_buffer = static_cast<const uint8_t*>(stream.ReadDirect(static_cast<size_t>(length)));
|
||||
|
||||
if (_buffer == nullptr)
|
||||
{
|
||||
if (length > stream.GetLength() - stream.GetPosition())
|
||||
throw IOException("Buffer Will Read Past the End of the Stream");
|
||||
|
||||
_bufferLength = bufferLength;
|
||||
_buffer = OpenRCT2::Memory::Allocate<const uint8_t>(_bufferLength);
|
||||
}
|
||||
}
|
||||
|
||||
StreamReadBuffer::~StreamReadBuffer()
|
||||
{
|
||||
if (_bufferLength > 0)
|
||||
OpenRCT2::Memory::Free(_buffer);
|
||||
|
||||
_buffer = nullptr;
|
||||
_bufferLength = 0;
|
||||
_remaining = 0;
|
||||
}
|
||||
|
||||
StreamReadBuffer::StreamReadBuffer(StreamReadBuffer&& other) noexcept
|
||||
{
|
||||
_buffer = other._buffer;
|
||||
_bufferLength = other._bufferLength;
|
||||
_remaining = other._remaining;
|
||||
|
||||
other._buffer = nullptr;
|
||||
other._bufferLength = 0;
|
||||
other._remaining = 0;
|
||||
}
|
||||
|
||||
StreamReadBuffer& StreamReadBuffer::operator=(StreamReadBuffer&& other) noexcept
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
_buffer = other._buffer;
|
||||
_bufferLength = other._bufferLength;
|
||||
_remaining = other._remaining;
|
||||
|
||||
other._buffer = nullptr;
|
||||
other._bufferLength = 0;
|
||||
other._remaining = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::pair<const void*, size_t> StreamReadBuffer::ReadBlock(IStream& stream, size_t maxLength)
|
||||
{
|
||||
const uint8_t* ptr = _buffer;
|
||||
size_t len = static_cast<size_t>(std::min<uint64_t>(_remaining, maxLength));
|
||||
if (_bufferLength == 0)
|
||||
{
|
||||
_buffer += len;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = static_cast<size_t>(std::min(len, _bufferLength));
|
||||
stream.Read(const_cast<uint8_t*>(ptr), len);
|
||||
}
|
||||
_remaining -= len;
|
||||
return { ptr, len };
|
||||
}
|
||||
|
||||
StreamWriteBuffer::StreamWriteBuffer(IStream& stream, uint64_t length, size_t bufferLength)
|
||||
{
|
||||
OpenRCT2::Guard::Assert(bufferLength > 0);
|
||||
|
||||
_remaining = length;
|
||||
if (length <= std::numeric_limits<size_t>::max())
|
||||
_buffer = static_cast<uint8_t*>(stream.WriteDirectStart(static_cast<size_t>(length)));
|
||||
|
||||
if (_buffer == nullptr)
|
||||
{
|
||||
_bufferLength = bufferLength;
|
||||
_buffer = OpenRCT2::Memory::Allocate<uint8_t>(_bufferLength);
|
||||
}
|
||||
}
|
||||
|
||||
StreamWriteBuffer::~StreamWriteBuffer()
|
||||
{
|
||||
if (_bufferLength > 0)
|
||||
OpenRCT2::Memory::Free(_buffer);
|
||||
|
||||
_buffer = nullptr;
|
||||
_bufferLength = 0;
|
||||
_remaining = 0;
|
||||
}
|
||||
|
||||
StreamWriteBuffer::StreamWriteBuffer(StreamWriteBuffer&& other) noexcept
|
||||
{
|
||||
_buffer = other._buffer;
|
||||
_bufferLength = other._bufferLength;
|
||||
_remaining = other._remaining;
|
||||
|
||||
other._buffer = nullptr;
|
||||
other._bufferLength = 0;
|
||||
other._remaining = 0;
|
||||
}
|
||||
|
||||
StreamWriteBuffer& StreamWriteBuffer::operator=(StreamWriteBuffer&& other) noexcept
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
_buffer = other._buffer;
|
||||
_bufferLength = other._bufferLength;
|
||||
_remaining = other._remaining;
|
||||
|
||||
other._buffer = nullptr;
|
||||
other._bufferLength = 0;
|
||||
other._remaining = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::pair<void*, size_t> StreamWriteBuffer::WriteBlockStart(size_t maxLength)
|
||||
{
|
||||
size_t len = static_cast<size_t>(std::min<uint64_t>(_remaining, maxLength));
|
||||
if (_bufferLength > 0)
|
||||
len = std::min(len, _bufferLength);
|
||||
|
||||
return { _buffer, len };
|
||||
}
|
||||
|
||||
void StreamWriteBuffer::WriteBlockCommit(IStream& stream, size_t length)
|
||||
{
|
||||
if (_bufferLength == 0)
|
||||
{
|
||||
stream.WriteDirectCommit(length);
|
||||
_buffer += length;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream.Write(_buffer, length);
|
||||
}
|
||||
_remaining -= length;
|
||||
}
|
||||
} // namespace OpenRCT2
|
||||
Reference in New Issue
Block a user