I would like to have some facility which makes a std::ostream
(or derived) automatically ident on encountering special characters (or special objects). Let's assume that the special characters are <
and >
. In this case the following input test0<test1<test2, test3<test4> > >
should produce the following output:
test0<
test1<
test2,
test3<
test4
>
>
>
How would one go to implement this?
boost::iostreams makes this fairly easy, you can define filters then chain them together with an output stream to transform the input to the desired output:
#include <iostream>
#include <boost/iostreams/filtering_stream.hpp>
namespace io = boost::iostreams;
struct QuoteOutputFilter {
typedef char char_type;
typedef io::output_filter_tag category;
int indent = 0;
template<typename Sink>
bool newLine(Sink& snk)
{
std::string str = "\n" + std::string(indent * 4, ' ');
return io::write(snk, str.c_str(), str.size());
}
template<typename Sink>
bool put(Sink& snk, char c)
{
switch (c)
{
case '<':
io::put(snk, c);
indent += 1;
return newLine(snk);
case ',':
io::put(snk, c);
return newLine(snk);
case '>':
indent -= 1;
newLine(snk);
return io::put(snk, c);
default:
return io::put(snk, c);
}
}
};
int main()
{
io::filtering_ostream out;
out.push(QuoteOutputFilter());
out.push(std::cout);
out << "test0<test1<test2, test3<test4> > >";
}