forked from Alepha/Alepha
Make the underlying streambuf private in stacks.
This commit is contained in:
@ -4,6 +4,9 @@ static_assert( __cplusplus > 2020'99 );
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
|
||||
namespace Alepha::Hydrogen::IOStreams::detail::StackableStreambuf_m
|
||||
{
|
||||
namespace
|
||||
@ -47,13 +50,26 @@ namespace Alepha::Hydrogen::IOStreams::detail::StackableStreambuf_m
|
||||
const auto *const current= dynamic_cast< StackableStreambuf * >( os.rdbuf() );
|
||||
if( not current ) return false;
|
||||
|
||||
os.rdbuf( current->underlying );
|
||||
current->unhook( os );
|
||||
|
||||
releaseTop( os, token );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
releaseTop( std::istream &is )
|
||||
{
|
||||
const auto *const current= dynamic_cast< StackableStreambuf * >( is.rdbuf() );
|
||||
if( not current ) return false;
|
||||
|
||||
current->unhook( is );
|
||||
|
||||
releaseTop( is, token );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void
|
||||
releaseStack( std::ios_base &ios )
|
||||
{
|
||||
@ -84,6 +100,13 @@ namespace Alepha::Hydrogen::IOStreams::detail::StackableStreambuf_m
|
||||
return os;
|
||||
}
|
||||
|
||||
std::istream &
|
||||
impl::operator >> ( std::istream &is, PopStack )
|
||||
{
|
||||
if( not releaseTop( is ) ) throw std::logic_error( "IStream has no stacked streambufs!" );
|
||||
return is;
|
||||
}
|
||||
|
||||
StackableStreambuf::~StackableStreambuf() {}
|
||||
|
||||
StackableStreambuf::StackableStreambuf( std::ios &host )
|
||||
@ -111,4 +134,9 @@ namespace Alepha::Hydrogen::IOStreams::detail::StackableStreambuf_m
|
||||
for( std::streamsize i= 0; i< amt; ++i ) overflow( data[ i ] );
|
||||
return amt;
|
||||
}
|
||||
|
||||
void StackableStreambuf::unhook( std::ostream &os ) const { os.rdbuf( underlying ); }
|
||||
void StackableStreambuf::unhook( std::istream &is ) const { is.rdbuf( underlying ); }
|
||||
|
||||
std::ostream &StackableStreambuf::out( std::ostream &&res ) const { res.rdbuf( underlying ); return *&res; }
|
||||
}
|
||||
|
@ -24,19 +24,24 @@ namespace Alepha::Hydrogen::IOStreams ::detail:: StackableStreambuf_m
|
||||
struct exports::StackableStreambuf
|
||||
: virtual public std::streambuf
|
||||
{
|
||||
public:
|
||||
private:
|
||||
std::streambuf *underlying;
|
||||
|
||||
public:
|
||||
~StackableStreambuf() override;
|
||||
|
||||
// Children must be created by `new`.
|
||||
explicit StackableStreambuf( std::ios &host );
|
||||
|
||||
auto out() const { return std::ostream{ underlying }; }
|
||||
|
||||
virtual void writeChar( char ch )= 0;
|
||||
virtual void drain()= 0;
|
||||
|
||||
void unhook( std::ostream &os ) const;
|
||||
void unhook( std::istream &is ) const;
|
||||
|
||||
protected:
|
||||
std::ostream &out( std::ostream &&res= std::ostream{nullptr} ) const;
|
||||
|
||||
int overflow( const int ch ) override;
|
||||
|
||||
// Underflow is not overridden. A read-oriented
|
||||
|
Reference in New Issue
Block a user