2020-09-01 11:43:32 +02:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2020, the SerenityOS developers.
|
|
|
|
*
|
2021-04-22 01:24:48 -07:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-09-01 11:43:32 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <AK/ByteBuffer.h>
|
2021-04-27 00:09:02 +04:30
|
|
|
#include <AK/LEB128.h>
|
2020-09-01 11:43:32 +02:00
|
|
|
#include <AK/MemMem.h>
|
|
|
|
#include <AK/Stream.h>
|
|
|
|
#include <AK/Vector.h>
|
|
|
|
|
|
|
|
namespace AK {
|
|
|
|
|
|
|
|
class InputMemoryStream final : public InputStream {
|
|
|
|
public:
|
2020-09-15 12:08:00 +02:00
|
|
|
explicit InputMemoryStream(ReadonlyBytes bytes)
|
2020-09-01 11:43:32 +02:00
|
|
|
: m_bytes(bytes)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-09-13 12:24:17 +02:00
|
|
|
bool unreliable_eof() const override { return eof(); }
|
|
|
|
bool eof() const { return m_offset >= m_bytes.size(); }
|
2020-09-01 11:43:32 +02:00
|
|
|
|
|
|
|
size_t read(Bytes bytes) override
|
|
|
|
{
|
2020-09-05 16:39:56 +02:00
|
|
|
if (has_any_error())
|
|
|
|
return 0;
|
|
|
|
|
2022-04-01 20:58:27 +03:00
|
|
|
auto const count = min(bytes.size(), remaining());
|
2020-09-01 11:43:32 +02:00
|
|
|
__builtin_memcpy(bytes.data(), m_bytes.data() + m_offset, count);
|
|
|
|
m_offset += count;
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool read_or_error(Bytes bytes) override
|
|
|
|
{
|
|
|
|
if (remaining() < bytes.size()) {
|
|
|
|
set_recoverable_error();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
__builtin_memcpy(bytes.data(), m_bytes.data() + m_offset, bytes.size());
|
|
|
|
m_offset += bytes.size();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool discard_or_error(size_t count) override
|
|
|
|
{
|
|
|
|
if (remaining() < count) {
|
|
|
|
set_recoverable_error();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_offset += count;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void seek(size_t offset)
|
|
|
|
{
|
2021-02-23 20:42:32 +01:00
|
|
|
VERIFY(offset < m_bytes.size());
|
2020-09-01 11:43:32 +02:00
|
|
|
m_offset = offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
u8 peek_or_error() const
|
|
|
|
{
|
|
|
|
if (remaining() == 0) {
|
|
|
|
set_recoverable_error();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return m_bytes[m_offset];
|
|
|
|
}
|
|
|
|
|
2021-07-27 09:42:57 +02:00
|
|
|
template<typename ValueType>
|
|
|
|
bool read_LEB128_unsigned(ValueType& result) { return LEB128::read_unsigned(*this, result); }
|
2020-09-01 11:43:32 +02:00
|
|
|
|
2021-07-27 09:42:57 +02:00
|
|
|
template<typename ValueType>
|
|
|
|
bool read_LEB128_signed(ValueType& result) { return LEB128::read_signed(*this, result); }
|
2020-09-01 11:43:32 +02:00
|
|
|
|
|
|
|
ReadonlyBytes bytes() const { return m_bytes; }
|
|
|
|
size_t offset() const { return m_offset; }
|
|
|
|
size_t remaining() const { return m_bytes.size() - m_offset; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
ReadonlyBytes m_bytes;
|
|
|
|
size_t m_offset { 0 };
|
|
|
|
};
|
|
|
|
|
2020-09-15 12:08:00 +02:00
|
|
|
class OutputMemoryStream final : public OutputStream {
|
|
|
|
public:
|
|
|
|
explicit OutputMemoryStream(Bytes bytes)
|
|
|
|
: m_bytes(bytes)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t write(ReadonlyBytes bytes) override
|
|
|
|
{
|
2022-04-01 20:58:27 +03:00
|
|
|
auto const nwritten = bytes.copy_trimmed_to(m_bytes.slice(m_offset));
|
2020-09-15 12:08:00 +02:00
|
|
|
m_offset += nwritten;
|
|
|
|
return nwritten;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool write_or_error(ReadonlyBytes bytes) override
|
|
|
|
{
|
|
|
|
if (remaining() < bytes.size()) {
|
|
|
|
set_recoverable_error();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
write(bytes);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-09-15 12:18:31 +02:00
|
|
|
size_t fill_to_end(u8 value)
|
|
|
|
{
|
2022-04-01 20:58:27 +03:00
|
|
|
auto const nwritten = m_bytes.slice(m_offset).fill(value);
|
2020-09-15 12:18:31 +02:00
|
|
|
m_offset += nwritten;
|
|
|
|
return nwritten;
|
|
|
|
}
|
|
|
|
|
2020-09-20 12:32:30 +02:00
|
|
|
bool is_end() const { return remaining() == 0; }
|
|
|
|
|
2020-09-15 12:08:00 +02:00
|
|
|
ReadonlyBytes bytes() const { return { data(), size() }; }
|
|
|
|
Bytes bytes() { return { data(), size() }; }
|
|
|
|
|
2022-04-01 20:58:27 +03:00
|
|
|
u8 const* data() const { return m_bytes.data(); }
|
2020-09-15 12:08:00 +02:00
|
|
|
u8* data() { return m_bytes.data(); }
|
|
|
|
|
|
|
|
size_t size() const { return m_offset; }
|
|
|
|
size_t remaining() const { return m_bytes.size() - m_offset; }
|
2021-05-11 18:35:36 +02:00
|
|
|
void reset() { m_offset = 0; }
|
2020-09-15 12:08:00 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
size_t m_offset { 0 };
|
|
|
|
Bytes m_bytes;
|
|
|
|
};
|
|
|
|
|
2020-09-01 11:43:32 +02:00
|
|
|
}
|
|
|
|
|
2022-11-26 12:18:30 +01:00
|
|
|
#if USING_AK_GLOBALLY
|
2020-09-01 11:43:32 +02:00
|
|
|
using AK::InputMemoryStream;
|
|
|
|
using AK::InputStream;
|
2020-09-15 12:08:00 +02:00
|
|
|
using AK::OutputMemoryStream;
|
2022-11-26 12:18:30 +01:00
|
|
|
#endif
|