How to add indention to the stream operator

前端 未结 4 1244
予麋鹿
予麋鹿 2020-12-31 05:02

In our project we use the c++ stream operator (<<) in our object model to print out an easy readible format of the data. A simplified example is this:

         


        
4条回答
  •  一生所求
    2020-12-31 05:26

    The simplest solution is to slip a filtering streambuf between the ostream and the actual streambuf. Something like:

    class IndentingOStreambuf : public std::streambuf
    {
        std::streambuf*     myDest;
        bool                myIsAtStartOfLine;
        std::string         myIndent;
        std::ostream*       myOwner;
    protected:
        virtual int         overflow( int ch )
        {
            if ( myIsAtStartOfLine && ch != '\n' ) {
                myDest->sputn( myIndent.data(), myIndent.size() );
            }
            myIsAtStartOfLine = ch == '\n';
            return myDest->sputc( ch );
        }
    public:
        explicit            IndentingOStreambuf( 
                                std::streambuf* dest, int indent = 4 )
            : myDest( dest )
            , myIsAtStartOfLine( true )
            , myIndent( indent, ' ' )
            , myOwner( NULL )
        {
        }
        explicit            IndentingOStreambuf(
                                std::ostream& dest, int indent = 4 )
            : myDest( dest.rdbuf() )
            , myIsAtStartOfLine( true )
            , myIndent( indent, ' ' )
            , myOwner( &dest )
        {
            myOwner->rdbuf( this );
        }
        virtual             ~IndentingOStreambuf()
        {
            if ( myOwner != NULL ) {
                myOwner->rdbuf( myDest );
            }
        }
    };
    

    To insert, just create an instance of the streambuf:

    IndentingOStreambuf indent( std::cout );
    //  Indented output...
    

    When indent goes out of scope, everything returns to normal.

    (For logging, I have one that is a bit more complex: the LoggingOStreambuf takes __FILE__ and __LINE__ as arguments, sets myIndent to a formatted string with these arguments, plus a time stamp, resets it to an indentation string after each output, collects all of the output in an std::ostringstream, and outputs it atomically to myDest in the destructor.)

提交回复
热议问题