9 #ifndef STK_UTIL_UTIL_INDENTSTREAMBUF_HPP 10 #define STK_UTIL_UTIL_INDENTSTREAMBUF_HPP 17 static const char PUSH =
'\016';
18 static const char POP =
'\017';
19 static const char LEFT =
'\021';
39 template<
class Ch,
class Tr = std::
char_traits<Ch> >
69 : m_streamBuffer(stream_buffer),
74 m_indentSize(indent_size),
75 m_flags((
Flags) flags),
86 delete[] m_indentString;
93 void redirect(std::basic_streambuf<Ch, Tr> *stream_buffer) {
94 m_streamBuffer = stream_buffer;
105 return m_streamBuffer;
117 m_indentSize = indent_size;
119 delete[] m_indentString;
121 std::fill(m_indentString, m_indentString +
MAX_INDENT_LEVEL*m_indentSize, static_cast<Ch>(
' '));
132 m_flags = (
Flags) flags;
142 size_t indent_level() {
143 return std::min(m_indentLevel*m_indentSize, (
size_t)
MAX_INDENT_LEVEL*m_indentSize);
154 m_streamBuffer->sputn(m_indentString, indent_level());
155 m_leftJustify =
false;
156 m_atLineBegin =
false;
165 if (m_nextIndentLevel > m_indentLevel) {
167 m_streamBuffer->sputn(
" {", 2);
168 m_streamBuffer->sputc(Tr::to_int_type(
'\n'));
170 else if (m_nextIndentLevel < m_indentLevel) {
171 m_indentLevel = m_nextIndentLevel;
173 m_streamBuffer->sputc(Tr::to_int_type(
'\n'));
175 m_streamBuffer->sputn(m_indentString, indent_level());
176 m_streamBuffer->sputc(Tr::to_int_type(
'}'));
177 m_streamBuffer->sputc(Tr::to_int_type(
'\n'));
180 else if (!m_atLineBegin || (m_flags &
BLANK_LINES))
181 m_streamBuffer->sputc(Tr::to_int_type(
'\n'));
183 m_indentLevel = m_nextIndentLevel;
184 m_atLineBegin =
true;
197 virtual typename std::basic_streambuf<Ch, Tr>::int_type
overflow(
typename std::basic_streambuf<Ch, Tr>::int_type c) {
198 if (c == Tr::to_int_type(
'\n'))
200 else if (c == Tr::to_int_type(
POP)) {
201 if (m_nextIndentLevel != m_indentLevel)
203 if (m_indentLevel > 0)
204 m_nextIndentLevel = m_indentLevel - 1;
206 else if (c == Tr::to_int_type(
PUSH)) {
207 if (m_nextIndentLevel != m_indentLevel)
209 m_nextIndentLevel = m_indentLevel + 1;
211 else if (c == Tr::to_int_type(
LEFT)) {
212 m_leftJustify =
true;
216 m_streamBuffer->sputc(c);
235 virtual std::streamsize
xsputn(
const Ch *p, std::streamsize n) {
236 const Ch *p_end = p + n;
237 for (
const Ch *q = p; q != p_end; ++q) {
240 if (p == q && m_atLineBegin) {
241 if (Tr::to_int_type(*p) == Tr::to_int_type(
'\n')) {
245 else if (Tr::to_int_type(*p) == Tr::to_int_type(
POP)) {
247 if (m_nextIndentLevel != m_indentLevel)
249 if (m_indentLevel > 0)
250 m_nextIndentLevel = m_indentLevel - 1;
252 else if (Tr::to_int_type(*p) == Tr::to_int_type(
PUSH)) {
254 if (m_nextIndentLevel != m_indentLevel)
256 m_nextIndentLevel = m_indentLevel + 1;
258 else if (Tr::to_int_type(*p) == Tr::to_int_type(
LEFT)) {
260 m_leftJustify =
true;
266 if (Tr::to_int_type(*q) == Tr::to_int_type(
'\n')) {
268 m_streamBuffer->sputn(p, q - p);
272 else if (Tr::to_int_type(*q) == Tr::to_int_type(
POP)) {
274 m_streamBuffer->sputn(p, q - p);
276 if (m_nextIndentLevel != m_indentLevel)
278 if (m_indentLevel > 0)
279 m_nextIndentLevel = m_indentLevel - 1;
281 else if (Tr::to_int_type(*q) == Tr::to_int_type(
PUSH)) {
283 m_streamBuffer->sputn(p, q - p);
285 if (m_nextIndentLevel != m_indentLevel)
287 m_nextIndentLevel = m_indentLevel + 1;
289 else if (Tr::to_int_type(*q) == Tr::to_int_type(
LEFT)) {
290 m_leftJustify =
true;
297 m_streamBuffer->sputn(p, p_end - p);
298 m_atLineBegin =
false;
310 return m_streamBuffer->pubsync();
318 std::streambuf * m_streamBuffer;
321 size_t m_indentLevel;
322 size_t m_nextIndentLevel;
328 template<
class Ch,
class Tr>
329 std::basic_ostream<Ch, Tr> &push(std::basic_ostream<Ch, Tr> &os) {
336 template<
class Ch,
class Tr>
337 std::basic_ostream<Ch, Tr> &pop(std::basic_ostream<Ch, Tr> &os) {
345 template<
class Ch,
class Tr>
346 class indent_streambuf_throwsafe
348 explicit indent_streambuf_throwsafe(basic_indent_streambuf<Ch, Tr> &sb)
349 : m_indentStreambuf(sb),
350 m_indentLevel(sb.indent_level())
353 ~indent_streambuf_throwsafe() {
354 while (m_indentStreambuf.indent_level() > m_indentLevel)
355 m_indentStreambuf.pop();
359 basic_indent_streambuf<Ch, Tr> & m_indentStreambuf;
360 size_t m_indentLevel;
368 inline IndentFlags indent_flags(
int flags) {
374 template<
class Ch,
class Tr>
375 std::basic_ostream<Ch, Tr> &
376 operator<<(std::basic_ostream<Ch, Tr> &os, IndentFlags indent_flags) {
377 basic_indent_streambuf<Ch, Tr> *osb =
dynamic_cast<basic_indent_streambuf<Ch, Tr> *
>(os.rdbuf());
379 osb->set_flags(indent_flags.m_flags);
388 #endif // STK_UTIL_UTIL_INDENTSTREAMBUF_HPP virtual std::streamsize xsputn(const Ch *p, std::streamsize n)
Member function xsputn interprets the meta-characters or writes the specified characters to the desti...
void set_flags(unsigned flags)
Member function set_flags enables or disables the BLANK_LINES and BRACES written to the destination s...
virtual ~basic_indent_streambuf()
virtual std::basic_streambuf< Ch, Tr >::int_type overflow(typename std::basic_streambuf< Ch, Tr >::int_type c)
Member function overflow interprets a meta-character or writes the specified character to the destina...
virtual int sync()
Member function sync syncs the destination output stream buffer.
No braces on indentation shift.
Class basic_indent_streambuf implements a output streambuf that performs indentation, blank line removal and outline bracing, sending the result character stream to another output stream buffer.
Braces on indentation shift.
Maximum indentation level.
static const char LEFT
Meta-character to force left justification.
basic_indent_streambuf(std::basic_streambuf< Ch, Tr > *stream_buffer, size_t indent_size=2, unsigned flags=BRACES)
std::streambuf * get_stream_buffer()
Member function get_stream_buffer returns the current destination output stream buffer.
void set_indent_size(size_t indent_size)
Member function set_indent_size set the number of spaces to write for each indentation level...
No blank line are written.
static const char PUSH
Meta-character to increase indentation.
void redirect(std::basic_streambuf< Ch, Tr > *stream_buffer)
Member function redirect sets the destination output stream buffer.
static const char POP
Meta-character to decrease indentation.