aboutsummaryrefslogtreecommitdiff
path: root/include/cru/common/io/BufferStream.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/cru/common/io/BufferStream.h')
-rw-r--r--include/cru/common/io/BufferStream.h89
1 files changed, 89 insertions, 0 deletions
diff --git a/include/cru/common/io/BufferStream.h b/include/cru/common/io/BufferStream.h
new file mode 100644
index 00000000..64d1bb56
--- /dev/null
+++ b/include/cru/common/io/BufferStream.h
@@ -0,0 +1,89 @@
+#pragma once
+
+#include "../Buffer.h"
+#include "Stream.h"
+#include "../Exception.h"
+
+#include <condition_variable>
+#include <list>
+#include <mutex>
+
+namespace cru::io {
+class WriteAfterEofException : public Exception {
+ public:
+ using Exception::Exception;
+ ~WriteAfterEofException() override = default;
+};
+
+struct BufferStreamOptions {
+ /**
+ * @brief The size of a single buffer allocated each time new space is needed.
+ * Use default value if <= 0.
+ *
+ * When current buffer is full and there is no space for following data, a new
+ * buffer will be allocated and appended to the buffer list. Note if sum size
+ * of all buffers reaches the total_buffer_limit, no more buffer will be
+ * allocated but wait.
+ */
+ Index block_size = 0;
+
+ /**
+ * @brief Total size limit of saved data in buffer. Use default value if < 0.
+ * No limit if == 0.
+ *
+ * The size will be ceil(total_size_limit / block_size). When the buffer is
+ * filled, it will block and wait for user to read to get free space of buffer
+ * to continue read.
+ */
+ Index total_size_limit = 0;
+};
+
+class BufferStream : public Stream {
+ public:
+ /**
+ * Actually I have no ideas about the best value for this. May change it later
+ * when I get some ideas.
+ */
+ constexpr static Index kDefaultBlockSize = 1024;
+
+ /**
+ * Actually I have no ideas about the best value for this. May change it later
+ * when I get some ideas.
+ */
+ constexpr static Index kDefaultTotalSizeLimit = 1024;
+
+ public:
+ BufferStream(const BufferStreamOptions& options);
+
+ ~BufferStream() override;
+
+ 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() = 0;
+ Index Write(const std::byte* buffer, Index offset, Index size) = 0;
+
+ virtual void Flush();
+
+ virtual void Close();
+
+ void SetEof();
+
+ private:
+ bool CheckClosed();
+
+ private:
+ Index block_size_;
+ Index total_size_limit_;
+ Index block_count_limit_;
+
+ std::list<Buffer> buffer_list_;
+ bool eof_;
+
+ std::mutex mutex_;
+ std::condition_variable condition_variable_;
+};
+} // namespace cru::io