Inspired by the epic question about indenting std::ostream
instances, here is a codecvt class that will add the additional characters.
The class was adapted from the popular answer by @MartinYork: I copy-pasted the class, adapted it to use a distinct character, and rewrote the for loop into a form I found more natural.
Here's a working example.
#include <iostream>
#include <locale>
class augmented_newline_facet : public std::codecvt<char, char, std::mbstate_t>
{
const char addition = '-';
public:
explicit augmented_newline_facet(const char addition, size_t refs = 0) : std::codecvt<char,char,std::mbstate_t>(refs), addition{addition} {}
using result = std::codecvt_base::result;
using base = std::codecvt<char,char,std::mbstate_t>;
using intern_type = base::intern_type;
using extern_type = base::extern_type;
using state_type = base::state_type;
int& state(state_type& s) const {return *reinterpret_cast<int*>(&s);}
protected:
virtual result do_out(state_type& addition_needed,
const intern_type* rStart, const intern_type* rEnd, const intern_type*& rNewStart,
extern_type* wStart, extern_type* wEnd, extern_type*& wNewStart) const override
{
result res = std::codecvt_base::noconv;
while ((rStart < rEnd) && (wStart < wEnd))
{
// The last character seen was a newline.
// Thus we need to add the additional character and an extra newline.
if (state(addition_needed) == 1)
{
*wStart++ = addition;
*wStart++ = '\n';
state(addition_needed) = 0;
res = std::codecvt_base::ok;
continue;
}
else
{
// Copy the next character.
*wStart = *rStart;
}
// If the character copied was a '\n' mark that state
if (*rStart == '\n')
{
state(addition_needed) = 1;
}
++rStart;
++wStart;
}
if (rStart != rEnd)
{
res = std::codecvt_base::partial;
}
rNewStart = rStart;
wNewStart = wStart;
return res;
}
virtual bool do_always_noconv() const throw() override
{
return false;
}
};
int main(int argc, char* argv[]) {
std::ios::sync_with_stdio(false);
std::cout.imbue(std::locale(std::locale::classic(),
new augmented_newline_facet{'-'}));
for (int i = 0; i < 5; ++i)
{
std::cout << "Line " << i << std::endl;
}
}