diff options
Diffstat (limited to 'include/cru/common/io')
-rw-r--r-- | include/cru/common/io/AutoReadStream.h | 25 | ||||
-rw-r--r-- | include/cru/common/io/BufferStream.h | 17 | ||||
-rw-r--r-- | include/cru/common/io/CFileStream.h | 29 | ||||
-rw-r--r-- | include/cru/common/io/MemoryStream.h | 34 | ||||
-rw-r--r-- | include/cru/common/io/ProxyStream.h | 22 | ||||
-rw-r--r-- | include/cru/common/io/Stream.h | 86 |
6 files changed, 116 insertions, 97 deletions
diff --git a/include/cru/common/io/AutoReadStream.h b/include/cru/common/io/AutoReadStream.h index b416d050..759d5026 100644 --- a/include/cru/common/io/AutoReadStream.h +++ b/include/cru/common/io/AutoReadStream.h @@ -1,10 +1,10 @@ #pragma once -#include "../SelfResolvable.h" #include "BufferStream.h" #include "Stream.h" #include <mutex> +#include <thread> namespace cru::io { struct AutoReadStreamOptions { @@ -30,8 +30,7 @@ struct AutoReadStreamOptions { * @brief A stream that wraps another stream and auto read it into a buffer in a * background thread. */ -class CRU_BASE_API AutoReadStream : public Stream, - public SelfResolvable<AutoReadStream> { +class CRU_BASE_API AutoReadStream : public Stream { public: /** * @brief Wrap a stream and auto read it in background. @@ -46,20 +45,18 @@ class CRU_BASE_API AutoReadStream : public Stream, ~AutoReadStream() override; public: - bool CanSeek() override; - Index Seek(Index offset, SeekOrigin origin = SeekOrigin::Current) override; + CRU_STREAM_IMPLEMENT_CLOSE_BY_DO_CLOSE - bool CanRead() override; - Index Read(std::byte* buffer, Index offset, Index size) override; + void BeginToDrop(bool auto_delete = true); - bool CanWrite() override; - Index Write(const std::byte* buffer, Index offset, Index size) override; - - void Flush() override; - - void Close() override; + protected: + Index DoRead(std::byte* buffer, Index offset, Index size) override; + Index DoWrite(const std::byte* buffer, Index offset, Index size) override; + void DoFlush() override; private: + void DoClose(); + void BackgroundThreadRun(); private: @@ -69,5 +66,7 @@ class CRU_BASE_API AutoReadStream : public Stream, Index size_per_read_; std::unique_ptr<BufferStream> buffer_stream_; std::mutex buffer_stream_mutex_; + + std::thread background_thread_; }; } // namespace cru::io diff --git a/include/cru/common/io/BufferStream.h b/include/cru/common/io/BufferStream.h index 16ba999b..5ebff546 100644 --- a/include/cru/common/io/BufferStream.h +++ b/include/cru/common/io/BufferStream.h @@ -59,21 +59,18 @@ struct BufferStreamOptions { class BufferStream : public Stream { public: BufferStream(const BufferStreamOptions& options); - ~BufferStream() override; - bool CanSeek() override; - Index Seek(Index offset, SeekOrigin origin = SeekOrigin::Current) override; + CRU_STREAM_IMPLEMENT_CLOSE_BY_DO_CLOSE - bool CanRead() override; - Index Read(std::byte* buffer, Index offset, Index size) override; - using Stream::Read; + void SetEof(); - bool CanWrite() override; - Index Write(const std::byte* buffer, Index offset, Index size) override; - using Stream::Write; + protected: + Index DoRead(std::byte* buffer, Index offset, Index size) override; + Index DoWrite(const std::byte* buffer, Index offset, Index size) override; - void SetEof(); + private: + void DoClose(); private: Index block_size_; diff --git a/include/cru/common/io/CFileStream.h b/include/cru/common/io/CFileStream.h index be23ac4a..0b58bdc9 100644 --- a/include/cru/common/io/CFileStream.h +++ b/include/cru/common/io/CFileStream.h @@ -17,32 +17,23 @@ class CRU_BASE_API CFileStream : public Stream { ~CFileStream() override; public: - bool CanSeek() override; - Index Seek(Index offset, SeekOrigin origin = SeekOrigin::Current) override; - Index Tell() override; - void Rewind() override; - - bool CanRead() override; - Index Read(std::byte* buffer, Index offset, Index size) override; - using Stream::Read; - - bool CanWrite() override; - Index Write(const std::byte* buffer, Index offset, Index size) override; - using Stream::Write; - - void Flush() override; - - void Close() override; + CRU_STREAM_IMPLEMENT_CLOSE_BY_DO_CLOSE std::FILE* GetHandle() const; + protected: + Index DoSeek(Index offset, SeekOrigin origin) override; + Index DoTell() override; + void DoRewind() override; + Index DoRead(std::byte* buffer, Index offset, Index size) override; + Index DoWrite(const std::byte* buffer, Index offset, Index size) override; + void DoFlush() override; + private: - void CheckClosed(); + void DoClose(); private: std::FILE* file_; - bool readable_; - bool writable_; bool auto_close_; }; } // namespace cru::io diff --git a/include/cru/common/io/MemoryStream.h b/include/cru/common/io/MemoryStream.h index a6243d67..a1f90c3b 100644 --- a/include/cru/common/io/MemoryStream.h +++ b/include/cru/common/io/MemoryStream.h @@ -7,38 +7,30 @@ namespace cru::io { class CRU_BASE_API MemoryStream : public Stream { public: - MemoryStream() = default; MemoryStream( std::byte* buffer, Index size, bool read_only = false, - std::function<void(std::byte* buffer, Index size)> release_func = {}) - : buffer_(buffer), - size_(size), - read_only_(read_only), - release_func_(std::move(release_func)) {} - - CRU_DELETE_COPY(MemoryStream) - CRU_DELETE_MOVE(MemoryStream) + std::function<void(std::byte* buffer, Index size)> release_func = {}); ~MemoryStream() override; public: - bool CanSeek() override; - Index Seek(Index offset, SeekOrigin origin = SeekOrigin::Current) override; + void Close() override; - bool CanRead() override; - Index Read(std::byte* buffer, Index offset, Index size) override; + std::byte* GetBuffer() const { return buffer_; } - bool CanWrite() override; - Index Write(const std::byte* buffer, Index offset, Index size) override; + protected: + Index DoSeek(Index offset, SeekOrigin origin) override; + Index DoGetSize() override { return size_; } + Index DoRead(std::byte* buffer, Index offset, Index size) override; + Index DoWrite(const std::byte* buffer, Index offset, Index size) override; - std::byte* GetBuffer() const { return buffer_; } - Index GetSize() override { return size_; } + private: + void DoClose(); private: - std::byte* buffer_ = nullptr; - Index size_ = 0; - Index position_ = 0; - bool read_only_ = false; + std::byte* buffer_; + Index size_; + Index position_; std::function<void(std::byte* buffer, Index size)> release_func_; }; } // namespace cru::io diff --git a/include/cru/common/io/ProxyStream.h b/include/cru/common/io/ProxyStream.h index d8848182..42ec9dfd 100644 --- a/include/cru/common/io/ProxyStream.h +++ b/include/cru/common/io/ProxyStream.h @@ -22,31 +22,21 @@ class ProxyStream : public Stream { public: explicit ProxyStream(ProxyStreamHandlers handlers); - CRU_DELETE_COPY(ProxyStream) - CRU_DELETE_MOVE(ProxyStream) - ~ProxyStream() override; public: - bool CanSeek() override; - Index Seek(Index offset, SeekOrigin origin = SeekOrigin::Current) override; - - bool CanRead() override; - Index Read(std::byte* buffer, Index offset, Index size) override; - - bool CanWrite() override; - Index Write(const std::byte* buffer, Index offset, Index size) override; - - void Flush() override; + CRU_STREAM_IMPLEMENT_CLOSE_BY_DO_CLOSE - void Close() override; + protected: + Index DoSeek(Index offset, SeekOrigin origin) override; + Index DoRead(std::byte* buffer, Index offset, Index size) override; + Index DoWrite(const std::byte* buffer, Index offset, Index size) override; + void DoFlush() override; private: - void CheckClosed(); void DoClose(); private: - bool closed_; ProxyStreamHandlers handlers_; }; } // namespace cru::io diff --git a/include/cru/common/io/Stream.h b/include/cru/common/io/Stream.h index 014cd472..e0b61627 100644 --- a/include/cru/common/io/Stream.h +++ b/include/cru/common/io/Stream.h @@ -6,7 +6,6 @@ #include "../String.h" #include <cstddef> -#include <vector> namespace cru::io { class CRU_BASE_API StreamOperationNotSupportedException : public Exception { @@ -36,41 +35,92 @@ class CRU_BASE_API StreamAlreadyClosedException : public Exception { static void Check(bool closed); }; +#define CRU_STREAM_IMPLEMENT_CLOSE_BY_DO_CLOSE \ + void Close() override { DoClose(); } + +#define CRU_STREAM_BEGIN_CLOSE \ + if (GetClosed()) return; \ + CloseGuard close_guard(this); + +/** + * All stream is thread-unsafe by default unless being documented. + */ class CRU_BASE_API Stream : public Object { + protected: + struct SupportedOperations { + std::optional<bool> can_seek; + std::optional<bool> can_read; + std::optional<bool> can_write; + }; + + struct CloseGuard { + explicit CloseGuard(Stream* stream) : stream(stream) {} + ~CloseGuard() { stream->SetClosed(true); } + Stream* stream; + }; + + protected: + explicit Stream(SupportedOperations supported_operations = {}); + Stream(std::optional<bool> can_seek, std::optional<bool> can_read, + std::optional<bool> can_write); + public: enum class SeekOrigin { Current, Begin, End }; - Stream() = default; - CRU_DELETE_COPY(Stream) CRU_DELETE_MOVE(Stream) ~Stream() override = default; public: - virtual bool CanSeek() = 0; - virtual Index Seek(Index offset, SeekOrigin origin = SeekOrigin::Current) = 0; - virtual Index Tell(); - virtual void Rewind(); - virtual Index GetSize(); - - virtual bool CanRead() = 0; - virtual Index Read(std::byte* buffer, Index offset, Index size) = 0; - virtual Index Read(std::byte* buffer, Index size); - - virtual bool CanWrite() = 0; - virtual Index Write(const std::byte* buffer, Index offset, Index size) = 0; - virtual Index Write(const std::byte* buffer, Index size); + bool CanSeek(); + Index Seek(Index offset, SeekOrigin origin = SeekOrigin::Current); + Index Tell(); + void Rewind(); + Index GetSize(); + + bool CanRead(); + Index Read(std::byte* buffer, Index offset, Index size); + Index Read(std::byte* buffer, Index size); + Index Read(char* buffer, Index offset, Index size); + Index Read(char* buffer, Index size); + + bool CanWrite(); + Index Write(const std::byte* buffer, Index offset, Index size); + Index Write(const std::byte* buffer, Index size); Index Write(const char* buffer, Index offset, Index size); Index Write(const char* buffer, Index size); + void Flush(); + virtual void Close() = 0; + virtual Buffer ReadToEnd(Index grow_size = 256); // Utf8 encoding. String ReadToEndAsUtf8String(); - virtual void Flush(); + protected: + virtual bool DoCanSeek(); + virtual bool DoCanRead(); + virtual bool DoCanWrite(); + virtual Index DoSeek(Index offset, SeekOrigin origin); + virtual Index DoTell(); + virtual void DoRewind(); + virtual Index DoGetSize(); + virtual Index DoRead(std::byte* buffer, Index offset, Index size); + virtual Index DoWrite(const std::byte* buffer, Index offset, Index size); + virtual void DoFlush(); + + void SetSupportedOperations(SupportedOperations supported_operations) { + supported_operations_ = std::move(supported_operations); + } + + bool GetClosed() { return closed_; } + void SetClosed(bool closed) { closed_ = closed; } + void CheckClosed() { StreamAlreadyClosedException::Check(closed_); } - virtual void Close(); + private: + std::optional<SupportedOperations> supported_operations_; + bool closed_; }; } // namespace cru::io |