94 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			94 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
 | |
| #pragma once
 | |
| 
 | |
| #if !defined(MIJIN_IO_STLSTREAM_HPP_INCLUDED)
 | |
| #define MIJIN_IO_STLSTREAM_HPP_INCLUDED 1
 | |
| 
 | |
| #include <array>
 | |
| #include <streambuf>
 | |
| #include "./stream.hpp"
 | |
| 
 | |
| namespace mijin
 | |
| {
 | |
| 
 | |
| //
 | |
| // public defines
 | |
| //
 | |
| 
 | |
| //
 | |
| // public constants
 | |
| //
 | |
| 
 | |
| //
 | |
| // public types
 | |
| //
 | |
| 
 | |
| template<typename TChar, typename TTraits = std::char_traits<TChar>>
 | |
| class BasicStreambufAdapter : public std::basic_streambuf<TChar, TTraits>
 | |
| {
 | |
| private:
 | |
|     using base_t = std::basic_streambuf<TChar, TTraits>;
 | |
|     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<TChar, BUFFER_SIZE> inBuffer_;
 | |
|     std::array<TChar, BUFFER_SIZE> 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<char>;
 | |
| 
 | |
| template<typename TChar, typename TTraits = std::char_traits<TChar>>
 | |
| class BasicIOStreamAdapter : public std::basic_iostream<TChar, TTraits>
 | |
| {
 | |
| private:
 | |
|     StreambufAdapter streambuf_;
 | |
| public:
 | |
|     BasicIOStreamAdapter(Stream& stream) noexcept : std::basic_iostream<TChar, TTraits>(&streambuf_), streambuf_(stream) {}
 | |
| };
 | |
| 
 | |
| using IOStreamAdapter = BasicIOStreamAdapter<char>;
 | |
| } // namespace mijin
 | |
| 
 | |
| #endif // !defined(MIJIN_IO_STLSTREAM_HPP_INCLUDED)
 |