Files
panopainter/src/foundation/binary_stream.cpp

143 lines
3.8 KiB
C++

#include "foundation/binary_stream.h"
namespace pp::foundation {
ByteReader::ByteReader(std::span<const std::byte> bytes) noexcept
: bytes_(bytes)
{
}
std::size_t ByteReader::position() const noexcept
{
return position_;
}
std::size_t ByteReader::size() const noexcept
{
return bytes_.size();
}
std::size_t ByteReader::remaining() const noexcept
{
return bytes_.size() - position_;
}
bool ByteReader::empty() const noexcept
{
return remaining() == 0;
}
Status ByteReader::seek(std::size_t position) noexcept
{
if (position > bytes_.size()) {
return Status::out_of_range("seek position is outside the stream");
}
position_ = position;
return Status::success();
}
Result<std::uint8_t> ByteReader::read_u8() noexcept
{
const auto bytes = read_bytes(1);
if (!bytes) {
return Result<std::uint8_t>::failure(bytes.status());
}
return Result<std::uint8_t>::success(static_cast<std::uint8_t>(bytes.value()[0]));
}
Result<std::uint16_t> ByteReader::read_u16_le() noexcept
{
const auto bytes = read_bytes(2);
if (!bytes) {
return Result<std::uint16_t>::failure(bytes.status());
}
const auto b0 = static_cast<std::uint16_t>(bytes.value()[0]);
const auto b1 = static_cast<std::uint16_t>(bytes.value()[1]);
return Result<std::uint16_t>::success(static_cast<std::uint16_t>(b0 | (b1 << 8U)));
}
Result<std::uint32_t> ByteReader::read_u32_le() noexcept
{
const auto bytes = read_bytes(4);
if (!bytes) {
return Result<std::uint32_t>::failure(bytes.status());
}
const auto b0 = static_cast<std::uint32_t>(bytes.value()[0]);
const auto b1 = static_cast<std::uint32_t>(bytes.value()[1]);
const auto b2 = static_cast<std::uint32_t>(bytes.value()[2]);
const auto b3 = static_cast<std::uint32_t>(bytes.value()[3]);
return Result<std::uint32_t>::success(b0 | (b1 << 8U) | (b2 << 16U) | (b3 << 24U));
}
Result<std::span<const std::byte>> ByteReader::read_bytes(std::size_t count) noexcept
{
if (count > remaining()) {
return Result<std::span<const std::byte>>::failure(
Status::out_of_range("read would move beyond the end of the stream"));
}
const auto start = position_;
position_ += count;
return Result<std::span<const std::byte>>::success(bytes_.subspan(start, count));
}
ByteWriter::ByteWriter(std::vector<std::byte>& bytes) noexcept
: bytes_(&bytes)
{
}
std::size_t ByteWriter::size() const noexcept
{
return bytes_ == nullptr ? 0 : bytes_->size();
}
Status ByteWriter::write_u8(std::uint8_t value)
{
if (bytes_ == nullptr) {
return Status::invalid_argument("writer has no backing storage");
}
bytes_->push_back(static_cast<std::byte>(value));
return Status::success();
}
Status ByteWriter::write_u16_le(std::uint16_t value)
{
if (bytes_ == nullptr) {
return Status::invalid_argument("writer has no backing storage");
}
bytes_->push_back(static_cast<std::byte>(value & 0xffU));
bytes_->push_back(static_cast<std::byte>((value >> 8U) & 0xffU));
return Status::success();
}
Status ByteWriter::write_u32_le(std::uint32_t value)
{
if (bytes_ == nullptr) {
return Status::invalid_argument("writer has no backing storage");
}
bytes_->push_back(static_cast<std::byte>(value & 0xffU));
bytes_->push_back(static_cast<std::byte>((value >> 8U) & 0xffU));
bytes_->push_back(static_cast<std::byte>((value >> 16U) & 0xffU));
bytes_->push_back(static_cast<std::byte>((value >> 24U) & 0xffU));
return Status::success();
}
Status ByteWriter::write_bytes(std::span<const std::byte> bytes)
{
if (bytes_ == nullptr) {
return Status::invalid_argument("writer has no backing storage");
}
bytes_->insert(bytes_->end(), bytes.begin(), bytes.end());
return Status::success();
}
}