36 template<
typename CharType,
typename Traits = std::
char_traits<CharType>>
41 using base_type = std::basic_streambuf<CharType, Traits>;
63 init(streambuf, max_line_length);
91 if (_base_streambuf !=
nullptr)
94 _base_streambuf = streambuf;
100 if (_max_line_length != 0)
108 _max_line_length = max_line_length;
112 if (_max_line_length > c_max_allowed_line_length)
114 _max_line_length = c_max_allowed_line_length;
118 if (_max_line_length > 0)
121 _buffer.resize(_max_line_length * 2);
129 return _indent_count;
136 if (_max_line_length > 0 &&
indent >= _max_line_length)
150 if (_base_streambuf ==
nullptr)
155 if (this->pubsync() != 0)
160 if (this->pptr() != this->pbase())
162 if (is_eof(this->sputc(_new_line)))
167 if (this->pubsync() != 0)
172 assert(this->pptr() == this->pbase());
175 _need_indent =
false;
183 if (
this != std::addressof(other))
186 std::swap(_base_streambuf, other._base_streambuf);
187 std::swap(_max_line_length, other._max_line_length);
191 std::swap(_indent_count, other._indent_count);
192 std::swap(_need_indent, other._need_indent);
209 if (_base_streambuf ==
nullptr)
211 return traits_type::eof();
215 if (_buffer.size() == 0)
220 return traits_type::not_eof(ch);
225 if (_need_indent && !is_new_line(ch))
229 return traits_type::eof();
240 return _base_streambuf->sputc(traits_type::to_char_type(ch));
244 if (this->pptr() > this->pbase() && !flush_buffer())
246 return traits_type::eof();
252 assert(this->pptr() != this->epptr());
253 this->sputc(traits_type::to_char_type(ch));
257 return traits_type::not_eof(ch);
266 if (_base_streambuf !=
nullptr && !is_eof(
overflow()))
268 return _base_streambuf->pubsync();
276 virtual void imbue(
const std::locale &loc)
override
278 if (_base_streambuf !=
nullptr)
281 _base_streambuf->pubimbue(loc);
282 update_locale_characters(loc);
291 if (_base_streambuf ==
nullptr)
296 auto start = this->pbase();
297 auto end = this->pptr();
300 assert(start !=
nullptr && end !=
nullptr);
302 std::streamsize count;
305 auto locale = this->getloc();
306 size_t line_length{};
309 line_length = _indent_count;
313 for (
auto current = start; current < end; ++current)
316 if (std::isspace(*current, locale))
318 potential_line_break = current;
322 if (++line_length > _max_line_length || traits_type::eq(*current, _new_line))
326 if (_need_indent && (line_length - _indent_count) > 1)
335 if (potential_line_break ==
nullptr)
337 potential_line_break = current;
342 new_start = potential_line_break + 1;
346 count = potential_line_break - start;
347 if (_base_streambuf->sputn(start, count) < count)
353 _base_streambuf->sputc(_new_line);
357 potential_line_break =
nullptr;
358 line_length = ((current + 1) - start) + _indent_count;
369 traits_type::move(this->pbase(), start,
static_cast<size_t>(count));
373 reset_put_area(
static_cast<int>(count));
379 void reset_put_area(
int valid_data = 0)
381 this->setp(_buffer.data(), _buffer.data() + _buffer.size());
384 this->pbump(valid_data);
389 void update_locale_characters(
const std::locale &loc)
391 auto &ctype = std::use_facet<std::ctype<char_type>>(loc);
392 _new_line = ctype.widen(
'\n');
393 _space = ctype.widen(
' ');
399 if (_base_streambuf ==
nullptr)
404 assert(_need_indent);
405 for (
size_t i = 0; i < _indent_count; ++i)
407 if (is_eof(_base_streambuf->sputc(_space)))
413 _need_indent =
false;
420 return traits_type::eq_int_type(ch, traits_type::to_int_type(_new_line));
426 return traits_type::eq_int_type(ch, traits_type::eof());
429 static constexpr
size_t c_max_allowed_line_length = 65536;
432 size_t _max_line_length{};
433 std::vector<char_type> _buffer;
436 size_t _indent_count{};
451 template<
typename CharType,
typename Traits>
452 auto get_line_wrapping_streambuf(std::basic_ostream<CharType, Traits> &stream)
458 struct set_indent_helper
466 template<
typename CharType,
typename Traits>
467 std::basic_ostream<CharType, Traits> &operator<<(std::basic_ostream<CharType, Traits> &stream,
const set_indent_helper &helper)
469 auto buffer = get_line_wrapping_streambuf(stream);
470 if (buffer !=
nullptr)
472 buffer->indent(helper.indent);
495 return details::set_indent_helper{indent};
514 template<
typename CharType,
typename Traits>
515 std::basic_ostream<CharType, Traits> &
reset_indent(std::basic_ostream<CharType, Traits> &stream)
517 auto buffer = details::get_line_wrapping_streambuf(stream);
518 if (buffer !=
nullptr)
520 if (!buffer->reset_indent())
522 stream.setstate(std::ios::failbit);
548 template<
typename CharType,
typename Traits = std::
char_traits<CharType>>
567 _buffer.init(base_stream.rdbuf(), max_line_length);
568 this->imbue(base_stream.rdbuf()->getloc());
612 if (
this != std::addressof(other))
615 _buffer.swap(other._buffer);
Output stream that wraps lines on white-space characters at the specified line length,...
Definition: line_wrapping_stream.h:550
void swap(basic_line_wrapping_ostream &other) noexcept
Swaps this basic_line_wrapping_ostream instance with another.
Definition: line_wrapping_stream.h:610
static basic_line_wrapping_ostream for_cout(short default_width=80)
Creates a basic_line_wrapping_ostream that writes to the standard output stream, using the console wi...
Definition: line_wrapping_stream.h:592
static basic_line_wrapping_ostream for_cerr(short default_width=80)
Creates a basic_line_wrapping_ostream that writes to the standard error stream, using the console wid...
Definition: line_wrapping_stream.h:602
std::basic_streambuf< CharType, Traits > streambuf_type
The concrete base stream buffer type used by this stream.
Definition: line_wrapping_stream.h:555
basic_line_wrapping_ostream(basic_line_wrapping_ostream &&other) noexcept
Move constructor.
Definition: line_wrapping_stream.h:573
std::basic_ostream< CharType, Traits > base_type
The concrete type that this class derives from.
Definition: line_wrapping_stream.h:553
basic_line_wrapping_ostream(base_type &base_stream, size_t max_line_length)
Initializes a new instance of the basic_line_wrapping_ostream class with the specified underlying str...
Definition: line_wrapping_stream.h:564
basic_line_wrapping_ostream & operator=(basic_line_wrapping_ostream &&other) noexcept
Move assignment operator.
Definition: line_wrapping_stream.h:581
Stream buffer that wraps lines on white-space characters at the specified line length,...
Definition: line_wrapping_stream.h:38
size_t indent() const
Gets the current number of spaces that each line is indented with.
Definition: line_wrapping_stream.h:127
void swap(basic_line_wrapping_streambuf &other) noexcept
Swaps the contents basic_line_wrapping_streambuf instance with another.
Definition: line_wrapping_stream.h:181
void indent(size_t indent) noexcept
Sets the number of spaces that each line is indented with.
Definition: line_wrapping_stream.h:134
basic_line_wrapping_streambuf() noexcept=default
Initializes a new instance of the basic_line_wrapping_streambuf class.
typename base_type::int_type int_type
Integer type used by the base type.
Definition: line_wrapping_stream.h:43
basic_line_wrapping_streambuf & operator=(basic_line_wrapping_streambuf &&other) noexcept
Move assignment operator.
Definition: line_wrapping_stream.h:73
void init(base_type *streambuf, size_t max_line_length) noexcept
Initializes this basic_line_wrapping_streambuf instance with the specified underlying stream buffer a...
Definition: line_wrapping_stream.h:89
virtual int sync() override
Flushes the buffer to the underlying stream buffer.
Definition: line_wrapping_stream.h:262
bool reset_indent()
Disables indentation for the next line.
Definition: line_wrapping_stream.h:148
virtual int_type overflow(int_type ch=traits_type::eof()) override
Ensure there is space to write at least one character to the buffer.
Definition: line_wrapping_stream.h:207
typename base_type::char_type char_type
Character type used by the base type.
Definition: line_wrapping_stream.h:45
virtual void imbue(const std::locale &loc) override
Change the locale of the stream buffer.
Definition: line_wrapping_stream.h:276
std::basic_streambuf< CharType, Traits > base_type
The concrete type that this class derives from.
Definition: line_wrapping_stream.h:41
basic_line_wrapping_streambuf(basic_line_wrapping_streambuf &&other) noexcept
Move constructor.
Definition: line_wrapping_stream.h:67
typename base_type::traits_type traits_type
Traits type used by the base type.
Definition: line_wrapping_stream.h:47
Provides helpers for using the console.
Namespace containing the core Ookii.CommandLine.Cpp types.
Definition: command_line_argument.h:16
std::basic_ostream< CharType, Traits > & reset_indent(std::basic_ostream< CharType, Traits > &stream)
IO manipulator that lets the next line start at the beginning of the line, without indenting it.
Definition: line_wrapping_stream.h:515
constexpr size_t use_console_width
Indicates that the basic_line_wrapping_streambuf should use the console width as the line length.
Definition: line_wrapping_stream.h:15
void swap(owned_or_borrowed_ptr< T > &left, owned_or_borrowed_ptr< T > &right) noexcept
Swaps two owned_or_borrowed_ptr instances.
Definition: owned_or_borrowed_ptr.h:219
details::set_indent_helper set_indent(size_t indent)
IO manipulator that changes the number of spaces that each line is indented with for a line wrapping ...
Definition: line_wrapping_stream.h:493
short get_console_width(short default_width=80) noexcept
Determines the width of the console.
Definition: console_helper.h:62
Template to determine the correct console streams based on the character type.
Definition: console_helper.h:95