Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
stream.hpp
Go to the documentation of this file.
1#pragma once
2
3// Unified Stream interface for bytewise I/O.
4//
5// A `Stream` presents a common surface across files, memory buffers, pipes,
6// sockets, and HTTP bodies. It is synchronous and byte-oriented; async
7// behavior is layered on top via `AsyncStream`, which dispatches Stream
8// operations on a background worker and delivers completions through the
9// `EventLoop`.
10//
11// The interface is minimal on purpose:
12// - `read(buf, n)` — non-blocking-style read; may return 0 with
13// StreamError::WouldBlock when no data is available.
14// - `write(buf, n)` — returns bytes written; may be partial.
15// - `close()` — idempotent; safe to call on a closed stream.
16// - `is_open()` — whether the stream is currently usable.
17//
18// Streams never throw from `read`/`write`. Errors surface as
19// `StreamError != Ok` in the returned `StreamResult`.
20
21#include <cstddef>
22#include <cstdint>
23#include <memory>
24#include <string>
25#include <string_view>
26#include <vector>
27
28namespace pulp::runtime {
29
38
46 std::size_t bytes = 0;
48
49 constexpr bool ok() const { return error == StreamError::Ok; }
50 constexpr bool would_block() const { return error == StreamError::WouldBlock; }
51 constexpr bool closed() const { return error == StreamError::Closed; }
52
53 static constexpr StreamResult make(std::size_t n) { return {n, StreamError::Ok}; }
54 static constexpr StreamResult fail(StreamError e) { return {0, e}; }
55};
56
62class Stream {
63public:
64 virtual ~Stream() = default;
65
66 Stream(const Stream&) = delete;
67 Stream& operator=(const Stream&) = delete;
68
71 virtual StreamResult read(std::uint8_t* buffer, std::size_t size) = 0;
72
76 virtual StreamResult write(const std::uint8_t* buffer, std::size_t size) = 0;
77
79 virtual void close() = 0;
80
82 virtual bool is_open() const = 0;
83
84protected:
85 Stream() = default;
86};
87
92class FileStream : public Stream {
93public:
94 enum class Mode : uint8_t { Read, Write, Append, ReadWrite };
95
96 FileStream() = default;
97 explicit FileStream(std::string_view path, Mode mode = Mode::Read);
98 ~FileStream() override;
99
102
104 bool open(std::string_view path, Mode mode = Mode::Read);
105
106 StreamResult read(std::uint8_t* buffer, std::size_t size) override;
107 StreamResult write(const std::uint8_t* buffer, std::size_t size) override;
108 void close() override;
109 bool is_open() const override { return handle_ != nullptr; }
110
112 bool flush();
113
115 std::size_t position() const;
116
117private:
118 void* handle_ = nullptr; // std::FILE*
119};
120
123class MemoryStream : public Stream {
124public:
125 MemoryStream() = default;
126
128 explicit MemoryStream(std::vector<std::uint8_t> initial);
129
130 StreamResult read(std::uint8_t* buffer, std::size_t size) override;
131 StreamResult write(const std::uint8_t* buffer, std::size_t size) override;
132 void close() override { open_ = false; }
133 bool is_open() const override { return open_; }
134
136 const std::vector<std::uint8_t>& buffer() const { return buffer_; }
137
139 void rewind() { read_pos_ = 0; }
140
142 void clear();
143
144 std::size_t size() const { return buffer_.size(); }
145 std::size_t read_position() const { return read_pos_; }
146
147private:
148 std::vector<std::uint8_t> buffer_;
149 std::size_t read_pos_ = 0;
150 bool open_ = true;
151};
152
153// Forward declaration — full definition requires named_pipe.hpp.
154class NamedPipe;
155
158class PipeStream : public Stream {
159public:
160 PipeStream() = default;
161 explicit PipeStream(std::unique_ptr<NamedPipe> pipe);
162 ~PipeStream() override;
163
165 PipeStream& operator=(PipeStream&&) noexcept;
166
167 StreamResult read(std::uint8_t* buffer, std::size_t size) override;
168 StreamResult write(const std::uint8_t* buffer, std::size_t size) override;
169 void close() override;
170 bool is_open() const override;
171
172 NamedPipe* pipe() { return pipe_.get(); }
173
174private:
175 std::unique_ptr<NamedPipe> pipe_;
176};
177
178} // namespace pulp::runtime
StreamResult read(std::uint8_t *buffer, std::size_t size) override
Read up to size bytes into buffer.
void close() override
Close the stream. Idempotent.
Mode
Definition stream.hpp:94
@ Write
Definition stream.hpp:94
@ Append
Definition stream.hpp:94
@ ReadWrite
Definition stream.hpp:94
@ Read
Definition stream.hpp:94
bool is_open() const override
True while the stream is usable for read/write.
Definition stream.hpp:109
bool flush()
Flush OS-level buffers to the underlying file.
FileStream(FileStream &&other) noexcept
FileStream(std::string_view path, Mode mode=Mode::Read)
StreamResult write(const std::uint8_t *buffer, std::size_t size) override
Write up to size bytes from buffer.
bool open(std::string_view path, Mode mode=Mode::Read)
Open path with the given mode. Returns true on success.
std::size_t position() const
Current byte position, or (size_t)-1 on error.
FileStream & operator=(FileStream &&other) noexcept
const std::vector< std::uint8_t > & buffer() const
Byte content currently in the stream (for inspection in tests).
Definition stream.hpp:136
StreamResult read(std::uint8_t *buffer, std::size_t size) override
Read up to size bytes into buffer.
void close() override
Close the stream. Idempotent.
Definition stream.hpp:132
bool is_open() const override
True while the stream is usable for read/write.
Definition stream.hpp:133
std::size_t size() const
Definition stream.hpp:144
MemoryStream(std::vector< std::uint8_t > initial)
Pre-fill the stream with existing bytes (copied in).
std::size_t read_position() const
Definition stream.hpp:145
StreamResult write(const std::uint8_t *buffer, std::size_t size) override
Write up to size bytes from buffer.
void rewind()
Reset the read cursor to the start.
Definition stream.hpp:139
void clear()
Clear all data and rewind.
Definition named_pipe.hpp:15
Wrap a value as a success result.
Definition result.hpp:42
bool is_open() const override
True while the stream is usable for read/write.
StreamResult write(const std::uint8_t *buffer, std::size_t size) override
Write up to size bytes from buffer.
PipeStream(PipeStream &&) noexcept
StreamResult read(std::uint8_t *buffer, std::size_t size) override
Read up to size bytes into buffer.
void close() override
Close the stream. Idempotent.
NamedPipe * pipe()
Definition stream.hpp:172
PipeStream(std::unique_ptr< NamedPipe > pipe)
virtual bool is_open() const =0
True while the stream is usable for read/write.
virtual ~Stream()=default
virtual StreamResult read(std::uint8_t *buffer, std::size_t size)=0
Read up to size bytes into buffer.
Stream & operator=(const Stream &)=delete
Stream(const Stream &)=delete
virtual void close()=0
Close the stream. Idempotent.
virtual StreamResult write(const std::uint8_t *buffer, std::size_t size)=0
Write up to size bytes from buffer.
Definition generated_event_source.hpp:33
StreamError
High-level error classification for Stream operations.
Definition stream.hpp:31
@ Closed
End-of-stream / peer closed / stream not open.
Definition stream.hpp:33
@ Invalid
Invalid argument or invalid state (e.g., read after close).
Definition stream.hpp:36
@ Ok
No error; bytes is authoritative.
Definition stream.hpp:32
@ WouldBlock
No data available now; try again later.
Definition stream.hpp:34
@ IoError
OS-level I/O failure (errno/GetLastError set by the backend).
Definition stream.hpp:35
@ other
Definition udev_monitor.hpp:26
STL namespace.
Result of a Stream read/write.
Definition stream.hpp:45
std::size_t bytes
Definition stream.hpp:46
constexpr bool would_block() const
Definition stream.hpp:50
constexpr bool ok() const
Definition stream.hpp:49
static constexpr StreamResult fail(StreamError e)
Definition stream.hpp:54
static constexpr StreamResult make(std::size_t n)
Definition stream.hpp:53
StreamError error
Definition stream.hpp:47
constexpr bool closed() const
Definition stream.hpp:51