diff --git a/IOStreams/StackableStreambuf.h b/IOStreams/StackableStreambuf.h index 50ffc17..843d4d4 100644 --- a/IOStreams/StackableStreambuf.h +++ b/IOStreams/StackableStreambuf.h @@ -21,11 +21,63 @@ namespace Alepha::Hydrogen::IOStreams ::detail:: StackableStreambuf_m struct PopStack{}; } + struct StackableStreambufUnderlyingShim + : protected virtual std::streambuf + { + private: + virtual std::streambuf *getUnderlying() const= 0; + + protected: + // EEEW. But to sidestep/circumvent, all this below is necessary. + auto + forwardOverflow( const int ch ) const + { + int (std::streambuf::*ov)( int )= &StackableStreambufUnderlyingShim::overflow; + return ( getUnderlying()->*ov )( ch ); + } + + auto + forwardUnderflow() const + { + int (std::streambuf::*uf)()= &StackableStreambufUnderlyingShim::underflow; + return (getUnderlying()->*uf)(); + } + + auto + underlying_eback() const + { + char *(std::streambuf::*eb)() const= &StackableStreambufUnderlyingShim::eback; + return (getUnderlying()->*eb)(); + } + + auto + underlying_gptr() const + { + char *(std::streambuf::*gp)() const= &StackableStreambufUnderlyingShim::gptr; + return (getUnderlying()->*gp)(); + } + + auto + underlying_egptr() const + { + char *(std::streambuf::*egp)() const= &StackableStreambufUnderlyingShim::egptr; + return (getUnderlying()->*egp)(); + } + + void + underlying_setg( char *const b, char *const g, char *const e ) + { + void (std::streambuf::*sg)( char *, char *, char * )= &StackableStreambufUnderlyingShim::setg; + return (getUnderlying()->*sg)( b, g, e ); + } + }; + struct exports::StackableStreambuf - : virtual public std::streambuf + : virtual public std::streambuf, virtual protected StackableStreambufUnderlyingShim { private: std::streambuf *underlying; + std::streambuf *getUnderlying() const final { return underlying; } public: ~StackableStreambuf() override; @@ -81,43 +133,6 @@ namespace Alepha::Hydrogen::IOStreams ::detail:: StackableStreambuf_m // available. std::streamsize xsputn( const char *data, std::streamsize amt ) override; - - // EEEW. But to sidestep/circumvent, all this below is necessary. - auto - forwardUnderflow() const - { - int (std::streambuf::*uf)()= &StackableStreambuf::underflow; - return (underlying->*uf)(); - } - - auto - underlying_eback() const - { - char *(std::streambuf::*eb)() const= &StackableStreambuf::eback; - return (underlying->*eb)(); - } - - auto - underlying_gptr() const - { - char *(std::streambuf::*gp)() const= &StackableStreambuf::gptr; - return (underlying->*gp)(); - } - - auto - underlying_egptr() const - { - char *(std::streambuf::*egp)() const= &StackableStreambuf::egptr; - return (underlying->*egp)(); - } - - void - underlying_setg( char *const b, char *const g, char *const e ) - { - void (std::streambuf::*sg)( char *, char *, char * )= &StackableStreambuf::setg; - return (underlying->*sg)( b, g, e ); - } - void assume_underlying() {