From 8e117e0f47ae8051b6c26c90a21d8b2bd4e939de Mon Sep 17 00:00:00 2001 From: Patrick Wuttke Date: Sun, 15 Sep 2024 14:45:30 +0200 Subject: [PATCH] Added wrapper to allow passing Mijin streams to functions that expect an STL stream. --- source/mijin/io/stlstream.hpp | 93 +++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 source/mijin/io/stlstream.hpp diff --git a/source/mijin/io/stlstream.hpp b/source/mijin/io/stlstream.hpp new file mode 100644 index 0000000..e84aac7 --- /dev/null +++ b/source/mijin/io/stlstream.hpp @@ -0,0 +1,93 @@ + +#pragma once + +#if !defined(MIJIN_IO_STLSTREAM_HPP_INCLUDED) +#define MIJIN_IO_STLSTREAM_HPP_INCLUDED 1 + +#include +#include +#include "./stream.hpp" + +namespace mijin +{ + +// +// public defines +// + +// +// public constants +// + +// +// public types +// + +template> +class BasicStreambufAdapter : public std::basic_streambuf +{ +private: + using base_t = std::basic_streambuf; + using char_type = base_t::char_type; + using int_type = base_t::int_type; + using traits_type = base_t::traits_type; + + static const std::size_t BUFFER_SIZE = 4096; + + Stream* stream_ = nullptr; + std::array inBuffer_; + std::array outBuffer_; +public: + explicit BasicStreambufAdapter(Stream& stream) noexcept : stream_(&stream) + { + base_t::setp(outBuffer_.data(), outBuffer_.data() + outBuffer_.size()); + } + + int_type underflow() override + { + std::size_t bytesRead = 0; + while (bytesRead == 0) + { + if (stream_->isAtEnd()) + { + return traits_type::eof(); + } + throwOnError(stream_->readRaw(inBuffer_, {.partial = true}, &bytesRead)); + } + base_t::setg(inBuffer_.data(), inBuffer_.data(), inBuffer_.data() + bytesRead); + return inBuffer_[0]; + } + + int_type overflow(int_type c) override + { + if (base_t::pptr() - base_t::pbase() > 0) + { + throwOnError(stream_->writeRaw(base_t::pbase(), base_t::pptr() - base_t::pbase())); + } + outBuffer_[0] = traits_type::to_char_type(c); + base_t::setp(outBuffer_.data() + 1, outBuffer_.data() + outBuffer_.size()); + return traits_type::not_eof(c); + } + + int sync() override + { + stream_->flush(); + return 0; + } +}; + +using StreambufAdapter = BasicStreambufAdapter; + +template> +class BasicIOStreamAdapter : public std::basic_iostream +{ +private: + StreambufAdapter streambuf_; +public: + BasicIOStreamAdapter(Stream& stream) noexcept : std::basic_iostream(&streambuf_), streambuf_(stream) {} +}; + +using IOStreamAdapter = BasicIOStreamAdapter; +} // namespace mijin + +#endif // !defined(MIJIN_IO_STLSTREAM_HPP_INCLUDED)