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