123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- /*
- * Copyright (c) 2021, kleines Filmröllchen <filmroellchen@serenityos.org>.
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
- #pragma once
- #include <AK/Error.h>
- #include <AK/NonnullOwnPtr.h>
- #include <AK/OwnPtr.h>
- #include <AK/Span.h>
- #include <AK/TypedTransfer.h>
- #include <LibCore/Stream.h>
- namespace Core::Stream {
- /// A stream class that allows for reading/writing on a preallocated memory area
- /// using a single read/write head.
- class FixedMemoryStream final : public SeekableStream {
- public:
- static ErrorOr<NonnullOwnPtr<FixedMemoryStream>> construct(Bytes bytes)
- {
- return adopt_nonnull_own_or_enomem<FixedMemoryStream>(new (nothrow) FixedMemoryStream(bytes));
- }
- static ErrorOr<NonnullOwnPtr<FixedMemoryStream>> construct(ReadonlyBytes bytes)
- {
- return adopt_nonnull_own_or_enomem<FixedMemoryStream>(new (nothrow) FixedMemoryStream(bytes));
- }
- virtual bool is_eof() const override { return m_offset >= m_bytes.size(); }
- virtual bool is_open() const override { return true; }
- // FIXME: It doesn't make sense to close an memory stream. Therefore, we don't do anything here. Is that fine?
- virtual void close() override { }
- // FIXME: It doesn't make sense to truncate a memory stream. Therefore, we don't do anything here. Is that fine?
- virtual ErrorOr<void> truncate(off_t) override { return Error::from_errno(ENOTSUP); }
- virtual ErrorOr<Bytes> read(Bytes bytes) override
- {
- auto to_read = min(remaining(), bytes.size());
- if (to_read == 0)
- return Bytes {};
- m_bytes.slice(m_offset, to_read).copy_to(bytes);
- m_offset += to_read;
- return bytes.trim(to_read);
- }
- virtual ErrorOr<off_t> seek(i64 offset, SeekMode seek_mode = SeekMode::SetPosition) override
- {
- switch (seek_mode) {
- case SeekMode::SetPosition:
- if (offset > static_cast<i64>(m_bytes.size()))
- return Error::from_string_literal("Offset past the end of the stream memory");
- m_offset = offset;
- break;
- case SeekMode::FromCurrentPosition:
- if (offset + static_cast<i64>(m_offset) > static_cast<i64>(m_bytes.size()))
- return Error::from_string_literal("Offset past the end of the stream memory");
- m_offset += offset;
- break;
- case SeekMode::FromEndPosition:
- if (offset > static_cast<i64>(m_bytes.size()))
- return Error::from_string_literal("Offset past the start of the stream memory");
- m_offset = m_bytes.size() - offset;
- break;
- }
- return static_cast<off_t>(m_offset);
- }
- virtual ErrorOr<size_t> write(ReadonlyBytes bytes) override
- {
- VERIFY(m_writing_enabled);
- // FIXME: Can this not error?
- auto const nwritten = bytes.copy_trimmed_to(m_bytes.slice(m_offset));
- m_offset += nwritten;
- return nwritten;
- }
- virtual ErrorOr<void> write_entire_buffer(ReadonlyBytes bytes) override
- {
- if (remaining() < bytes.size())
- return Error::from_string_literal("Write of entire buffer ends past the memory area");
- TRY(write(bytes));
- return {};
- }
- Bytes bytes()
- {
- VERIFY(m_writing_enabled);
- return m_bytes;
- }
- ReadonlyBytes bytes() const { return m_bytes; }
- size_t offset() const { return m_offset; }
- size_t remaining() const { return m_bytes.size() - m_offset; }
- protected:
- explicit FixedMemoryStream(Bytes bytes)
- : m_bytes(bytes)
- {
- }
- explicit FixedMemoryStream(ReadonlyBytes bytes)
- : m_bytes({ const_cast<u8*>(bytes.data()), bytes.size() })
- , m_writing_enabled(false)
- {
- }
- private:
- Bytes m_bytes;
- size_t m_offset { 0 };
- bool m_writing_enabled { true };
- };
- }
|