IndentingOutputStreamToOStream.h
// IndentingOutputStreamToOStream.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2008
#pragma once
#ifndef Ceda_cxUtils_IndentingOutputStreamToOStream_H
#define Ceda_cxUtils_IndentingOutputStreamToOStream_H
#include "StreamInterfaces.h"
#include "xchar.h"
#include "cxUtils.h"
#include <streambuf>
#include <ostream>
#include <stdio.h>
#ifdef _MSC_VER
// struct 'X' needs to have dll-interface to be used by clients of class 'Y'
#pragma warning(disable:4251)
// non dll-interface struct 'X' used as base for dll-interface class 'Y'
#pragma warning(disable:4275)
#endif
namespace ceda
{
///////////////////////////////////////////////////////////////////////////////////////////////////
// IndentingOutputStreamAsStreambuf
/*
Adapts a IOutputStream to a std::basic_streambuf<xchar> and also applies automatic indentation.
Note that
1) the ctor takes the IOutputStream to be decorated.
2) IndentingOutputStreamAsStreambuf inherits from streambuf in order to represent a
streambuf.
IndentingStreamBuf only supports writing and underflow() causes an assertion.
m_indent represents the current indentation (i.e. number of spaces) to be applied after every
linefeed. Initially it is zero.
The actual indentation is applied lazily, meaning that the indent isn't eagerly applied after
processing a linefeed. Instead it is triggered by subsequent writing. This is important to
ensure the indent can be changed after the linefeed and before subsequent writing.
A call to sync() flushes the IndentingStreamBuf, and this also causes the decorated
IOutputStream to be flushed as well (with a call to FlushStream()).
*/
class cxUtils_API IndentingOutputStreamAsStreambuf : public std::basic_streambuf<xchar, std::char_traits<xchar> >
{
public:
IndentingOutputStreamAsStreambuf(IOutputStream& outputStream);
~IndentingOutputStreamAsStreambuf();
// Implementation of streambuf
virtual int_type overflow(int_type nCh = EOF);
virtual int_type underflow();
virtual int sync();
void Indent(ssize_t offset) { m_indent += offset; }
ssize_t GetIndent() const { return m_indent; }
private:
void ProcessBuffer(const xchar* p1, const xchar* p2);
private:
enum { STREAM_BUFFER_SIZE = 4096 };
bool m_enableOverFlowInDestructor;
ssize_t m_indent;
bool m_needToIndent;
IOutputStream& m_outputStream;
xchar m_buffer[STREAM_BUFFER_SIZE];
};
///////////////////////////////////////////////////////////////////////////////////////////////////
// IndentingOutputStreamToOStream
// Looks like an ostream, and sends all the text onto a given IOutputStream
class cxUtils_API IndentingOutputStreamToOStream : public std::basic_ostream<xchar, std::char_traits<xchar> >
{
public:
IndentingOutputStreamToOStream(IOutputStream& outputStream);
void Indent(ssize_t offset) { m_streamBuf.Indent(offset); }
ssize_t GetIndent() const { return m_streamBuf.GetIndent(); }
private:
IndentingOutputStreamAsStreambuf m_streamBuf;
};
} // namespace ceda
#endif // include guard