// Copyright (C) 2012-2015 ChaosForge Ltd // http://chaosforge.org/ // // This file is part of Nova libraries. // For conditions of distribution and use, see copying.txt file in root folder. // // TODO: support for write operations, see http://www.mr-edd.co.uk/blog/beginners_guide_streambuf #include "nv/io/std_stream.hh" #include "nv/stl/math.hh" #include "nv/stl/utility.hh" using namespace nv; std_streambuf::std_streambuf( stream* source, bool owner /*= false*/, std::size_t bsize /*= 256*/, std::size_t put_back /*= 8 */ ) : m_stream( source ) , m_owner( owner ) , m_buffer( nv::max(bsize, put_back) + put_back ) , m_put_back( nv::max( put_back, std::size_t( 1 ) ) ) { char *end = &m_buffer.front() + m_buffer.size(); setg( end, end, end ); } std_streambuf::~std_streambuf() { if ( m_owner ) { delete m_stream; } } std_streambuf::int_type std_streambuf::underflow() { if (gptr() < egptr()) { // buffer not exhausted return traits_type::to_int_type(*gptr()); } char *base = &m_buffer.front(); char *start = base; if (eback() == base) // true when this isn't the first fill { // Make arrangements for putback characters std::copy( egptr() - m_put_back, egptr(), base ); start += m_put_back; } // start is now the start of the buffer, proper. size_t n = m_stream->read( start, 1, m_buffer.size() - static_cast(start - base) ); if (n == 0) { return traits_type::eof(); } // Set buffer pointers setg(base, start, start + n); return traits_type::to_int_type(*gptr()); }