Files
mrw-cxx/src/mrw/iomanip.hxx

113 lines
4.0 KiB
C++
Raw Normal View History

/*! @file
@id $Id$
*/
// 1 2 3 4 5 6 7 8
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
#ifndef __MRW__IOMANIP__
#define __MRW__IOMANIP__
#include <stdexcept>
#include <sstream>
#include <string>
#include <iomanip>
// check if code is compiled with a new C++11 compiler
// otherwise there is a fallback wich makes everything much more compliacted
#ifndef MRW__OLD_PRE11_COMPILER
#if __cplusplus < 201103L
/// Code is compiled with an old non C++11 standard compliant compiler
/** There are workarounds for old non C++11 compatible
compilers. These workarounds are deprecated, but will remain until
most compilers fully support C++11. So this workaround will be
removed in future releases, when support for C++11 is more
common. Only rely on this workaround, if you really have to.
@see oldcompiler for details on usage */
#define MRW__OLD_PRE11_COMPILER
#warning You need a C++11 compliant compiler, on gcc use option -std=c++11
#warning emulating C++11 - this changes the way you use the library
#warning this is deprecated and will be removed in future releases
#warning refere to the library documentation for more details
#endif
#endif
namespace mrw {
//! IO-Manipulator to split long lines into several shorter lines.
template <class _CharT = char, class _Traits = std::char_traits<_CharT> >
class basic_split /*: public std::basic_ostream<_CharT, _Traits>*/ {
public:
basic_split(const basic_split& o):
_width(o._width),
_indent(o._indent),
_fill(o._fill),
_buffer(o._buffer.str()),
_os(o._os) {
}
basic_split(int width=80, int indent=0, char fill=' '):
_width(width), _indent(indent), _fill(fill), _os(0) {
if (_width<_indent)
#ifdef MRW__OLD_PRE11_COMPILER
throw std::runtime_error(((std::stringstream&)
(std::stringstream()
<<"wrong use of split: width is "<<_width
<<" but should be larger than indent,"
<<" which is "<<_indent)).str());
#else
throw std::runtime_error("wrong use of split: width is "+
std::to_string(_width)+
" but should be larger than indent,"
" which is "+std::to_string(_indent));
#endif
}
virtual ~basic_split() {
flush();
}
friend basic_split& operator<<(std::basic_ostream<_CharT, _Traits>& os,
const basic_split& s) {
if (s._os!=&os) {
const_cast<basic_split&>(s).flush();
const_cast<basic_split&>(s)._os = &os;
}
return const_cast<basic_split&>(s);
}
template <typename T> basic_split& operator<<(const T& t) {
if (!_os)
throw std::runtime_error("wrong use of split, it is an io"
" manipulator and must be used within"
" a stream");
_buffer<<t;
while (_buffer.str().size()>=_width-_indent) {
if (_indent) *_os<<std::setw(_indent)<<std::setfill(_fill)<<_fill;
std::string::size_type pos
(_buffer.str().find_last_of(' ', _width-_indent));
std::string::size_type next(pos+1);
if (pos==std::string::npos) {
pos=_width-_indent;
next=pos;
}
*_os<<_buffer.str().substr(0, pos)<<std::endl;
_buffer.str(_buffer.str().substr(next));
}
return *this;
}
private:
void flush() {
if (_os) {
if (_indent) *_os<<std::setw(_indent)<<std::setfill(_fill)<<_fill;
*_os<<_buffer.str();
_buffer.clear();
}
}
private:
int _width;
int _indent;
char _fill;
std::stringstream _buffer;
std::basic_ostream<_CharT, _Traits>* _os;
};
typedef basic_split<char> ssplit;
}
#endif