#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)