40 template<
typename CharType,
typename Traits = std::
char_traits<CharType>>
45 using base_type = std::basic_streambuf<CharType, Traits>;
67 init(streambuf, max_line_length);
103 void init(
base_type *streambuf,
size_t max_line_length,
bool count_formatting =
false) noexcept
105 if (_base_streambuf !=
nullptr)
110 _base_streambuf = streambuf;
111 _count_formatting = count_formatting;
117 if (_max_line_length != 0)
125 _max_line_length = max_line_length;
129 if (_max_line_length > c_max_allowed_line_length)
131 _max_line_length = c_max_allowed_line_length;
135 if (_max_line_length > 0)
138 _buffer.resize(_max_line_length * 2);
145 this->setp(
nullptr,
nullptr);
152 return _indent_count;
159 if (_max_line_length > 0 &&
indent >= _max_line_length)
173 if (_base_streambuf ==
nullptr)
178 if (this->pubsync() != 0)
183 if (this->pptr() != this->pbase())
185 if (is_eof(this->sputc(_new_line)))
190 if (this->pubsync() != 0)
195 assert(this->pptr() == this->pbase());
198 _need_indent =
false;
206 if (
this != std::addressof(other))
208 base_type::swap(other);
209 std::swap(_base_streambuf, other._base_streambuf);
210 std::swap(_max_line_length, other._max_line_length);
211 std::swap(_buffer, other._buffer);
212 std::swap(_new_line, other._new_line);
213 std::swap(_space, other._space);
214 std::swap(_indent_count, other._indent_count);
215 std::swap(_need_indent, other._need_indent);
216 std::swap(_count_formatting, other._count_formatting);
235 virtual int sync(
bool flush_last_line)
237 if (_base_streambuf ==
nullptr)
245 return _base_streambuf->pubsync();
249 if (this->pptr() > this->pbase() && !flush_buffer(flush_last_line))
254 return _base_streambuf->pubsync();
270 if (_base_streambuf ==
nullptr)
272 return traits_type::eof();
276 if (_buffer.size() == 0)
281 return traits_type::not_eof(ch);
288 _need_indent = !_blank_line;
295 if (_need_indent && !write_indent())
297 return traits_type::eof();
304 return _base_streambuf->sputc(traits_type::to_char_type(ch));
308 if (this->pptr() > this->pbase() && !flush_buffer())
310 return traits_type::eof();
316 if (this->pptr() == this->epptr() && !grow_buffer())
318 return traits_type::eof();
322 assert(this->pptr() != this->epptr());
323 this->sputc(traits_type::to_char_type(ch));
327 return traits_type::not_eof(ch);
345 virtual void imbue(
const std::locale &loc)
override
347 if (_base_streambuf !=
nullptr)
350 _base_streambuf->pubimbue(loc);
351 update_locale_characters(loc);
356 using vt_helper_type = vt::details::vt_helper<CharType, Traits>;
360 bool flush_buffer(
bool flush_last_line =
false)
362 if (_base_streambuf ==
nullptr)
367 auto start = this->pbase();
368 auto end = this->pptr();
371 assert(start !=
nullptr && end !=
nullptr);
373 std::streamsize count;
376 auto locale = this->getloc();
377 size_t line_length{};
380 line_length = _indent_count;
384 for (
auto current = start; current < end; ++current)
387 if (std::isspace(*current, locale))
389 potential_line_break = current;
392 if (!_count_formatting && traits_type::eq(*current, vt_helper_type::c_escape))
394 auto vt_end = vt_helper_type::find_sequence_end(current + 1, end, locale);
395 if (vt_end ==
nullptr)
407 if (line_length >= _max_line_length || traits_type::eq(*current, _new_line))
413 line_length -= _indent_count;
414 if (line_length > 0 && !write_indent())
421 if (potential_line_break ==
nullptr)
423 potential_line_break = current;
428 new_start = potential_line_break + 1;
432 count = potential_line_break - start;
433 if (_base_streambuf->sputn(start, count) < count)
439 if (is_eof(_base_streambuf->sputc(_new_line)))
446 potential_line_break =
nullptr;
447 _need_indent = line_length > 0;
448 line_length = ((current + 1) - start);
451 line_length += _indent_count;
464 if (_need_indent && !write_indent())
471 if (_base_streambuf->sputn(start, count) < count ||
472 is_eof(_base_streambuf->sputc(_new_line)))
480 else if (start > this->pbase())
490 traits_type::move(this->pbase(), start,
static_cast<size_t>(count));
494 reset_put_area(
static_cast<int>(count));
502 assert(this->epptr() == this->pptr());
503 auto old_size =
static_cast<int>(_buffer.size());
504 auto new_size = old_size * 2;
506 if (new_size < old_size)
508 new_size = std::numeric_limits<std::int32_t>::max();
511 if (new_size == old_size)
516 _buffer.resize(new_size);
517 reset_put_area(old_size);
522 void reset_put_area(
int valid_data = 0)
524 this->setp(_buffer.data(), _buffer.data() + _buffer.size());
527 this->pbump(valid_data);
532 void update_locale_characters(
const std::locale &loc)
534 auto &ctype = std::use_facet<std::ctype<char_type>>(loc);
535 _new_line = ctype.widen(
'\n');
536 _space = ctype.widen(
' ');
542 if (_base_streambuf ==
nullptr)
547 assert(_need_indent);
548 for (
size_t i = 0; i < _indent_count; ++i)
550 if (is_eof(_base_streambuf->sputc(_space)))
556 _need_indent =
false;
563 return traits_type::eq_int_type(ch, traits_type::to_int_type(_new_line));
569 return traits_type::eq_int_type(ch, traits_type::eof());
572 static constexpr
size_t c_max_allowed_line_length = 65536;
575 size_t _max_line_length{};
576 std::vector<char_type> _buffer;
579 size_t _indent_count{};
581 bool _blank_line{
true};
582 bool _count_formatting{};
596 template<
typename CharType,
typename Traits>
597 auto get_line_wrapping_streambuf(std::basic_ostream<CharType, Traits> &stream)
603 struct set_indent_helper
611 template<
typename CharType,
typename Traits>
612 std::basic_ostream<CharType, Traits> &operator<<(std::basic_ostream<CharType, Traits> &stream,
const set_indent_helper &helper)
614 auto buffer = get_line_wrapping_streambuf(stream);
615 if (buffer !=
nullptr)
617 buffer->indent(helper.indent);
625 bool flush_last_line;
628 template<
typename CharType,
typename Traits>
629 std::basic_ostream<CharType, Traits> &operator<<(std::basic_ostream<CharType, Traits> &stream,
const flush_helper &helper)
631 auto buffer = get_line_wrapping_streambuf(stream);
632 if (buffer !=
nullptr)
634 buffer->sync(helper.flush_last_line);
660 return details::set_indent_helper{indent};
679 template<
typename CharType,
typename Traits>
680 std::basic_ostream<CharType, Traits> &
reset_indent(std::basic_ostream<CharType, Traits> &stream)
682 auto buffer = details::get_line_wrapping_streambuf(stream);
683 if (buffer !=
nullptr)
685 if (!buffer->reset_indent())
687 stream.setstate(std::ios::failbit);
719 inline details::flush_helper
flush(
bool flush_last_line)
721 return {flush_last_line};
747 template<
typename CharType,
typename Traits = std::
char_traits<CharType>>
776 init(base_stream, max_line_length, count_formatting);
788 void init(
base_type &base_stream,
size_t max_line_length,
bool count_formatting =
false)
790 _buffer.init(base_stream.rdbuf(), max_line_length, count_formatting);
791 this->imbue(base_stream.rdbuf()->getloc());
835 if (
this != std::addressof(other))
837 base_type::swap(other);
838 _buffer.swap(other._buffer);
859 if (_buffer.sync(flush_last_line) < 0)
861 this->setstate(basic_line_wrapping_ostream::badbit);
876 template <
class T,
class =
void>
877 struct is_allocator : std::false_type
882 struct is_allocator<T, std::void_t<typename T::value_type, decltype(std::declval<T&>().deallocate(
883 std::declval<T&>().allocate(size_t{ 1 }), size_t{ 1 })) >>
909 template<
typename CharType,
typename Traits = std::
char_traits<CharType>,
typename Allocator = std::allocator<CharType>>
918 using string_type = std::basic_string<CharType, Traits, Allocator>;
930 this->
init(_stringstream, max_line_length, count_formatting);
939 return _stringstream.str();
946 template<typename SAlloc, std::enable_if_t<details::is_allocator<SAlloc>::value,
int> = 0>
947 std::basic_string<CharType, Traits, SAlloc>
str(
const SAlloc &alloc)
const
949 return _stringstream.str(alloc);
958 return std::move(_stringstream).str();
965 _stringstream.str(s);
970 template<
typename SAlloc>
971 void str(
const std::basic_string<CharType, Traits, SAlloc> &s)
973 _stringstream.str(s);
980 _stringstream.str(std::move(s));
987 std::basic_string_view<CharType, Traits>
view() const noexcept
989 return _stringstream.view();
Output stream that wraps lines on white-space characters at the specified line length,...
Definition: line_wrapping_stream.h:749
void swap(basic_line_wrapping_ostream &other) noexcept
Swaps this basic_line_wrapping_ostream instance with another.
Definition: line_wrapping_stream.h:833
void flush(bool flush_last_line)
Flushes the buffer to the underlying stream buffer, optionally including the the final,...
Definition: line_wrapping_stream.h:857
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:815
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:825
basic_line_wrapping_ostream(base_type &base_stream, size_t max_line_length, bool count_formatting=false)
Initializes a new instance of the basic_line_wrapping_ostream class with the specified underlying str...
Definition: line_wrapping_stream.h:773
std::basic_streambuf< CharType, Traits > streambuf_type
The concrete base stream buffer type used by this stream.
Definition: line_wrapping_stream.h:754
basic_line_wrapping_ostream()
Initializes a new instance of the basic_line_wrapping_ostream class.
Definition: line_wrapping_stream.h:759
basic_line_wrapping_ostream(basic_line_wrapping_ostream &&other) noexcept
Move constructor.
Definition: line_wrapping_stream.h:796
std::basic_ostream< CharType, Traits > base_type
The concrete type that this class derives from.
Definition: line_wrapping_stream.h:752
void init(base_type &base_stream, size_t max_line_length, bool count_formatting=false)
Initializes a new instance of the basic_line_wrapping_ostream class with the specified underlying str...
Definition: line_wrapping_stream.h:788
basic_line_wrapping_ostream & operator=(basic_line_wrapping_ostream &&other) noexcept
Move assignment operator.
Definition: line_wrapping_stream.h:804
Output string stream that wraps lines on white-space characters at the specified line length,...
Definition: line_wrapping_stream.h:911
void str(const std::basic_string< CharType, Traits, SAlloc > &s)
Replaces the contents of the underlying string.
Definition: line_wrapping_stream.h:971
std::basic_string< CharType, Traits, SAlloc > str(const SAlloc &alloc) const
Gets a copy of the underlying string object, using alloc as allocator.
Definition: line_wrapping_stream.h:947
basic_line_wrapping_ostringstream(size_t max_line_length, bool count_formatting=false)
Initializes a new instance of the basic_line_wrapping_ostringstream class with the specified maximum ...
Definition: line_wrapping_stream.h:928
std::basic_ostringstream< CharType, Traits, Allocator > ostringstream_type
The concrete type of std::basic_ostringstream used.
Definition: line_wrapping_stream.h:916
std::basic_string_view< CharType, Traits > view() const noexcept
Gets a view over the underlying string.
Definition: line_wrapping_stream.h:987
void str(const string_type &s)
Replaces the contents of the underlying string.
Definition: line_wrapping_stream.h:963
void str(string_type &&s)
Replaces the contents of the underlying string.
Definition: line_wrapping_stream.h:978
std::basic_string< CharType, Traits, Allocator > string_type
The concrete type of std::basic_string used.
Definition: line_wrapping_stream.h:918
string_type str() &&
Gets a string move-constructed from the underlying string.
Definition: line_wrapping_stream.h:956
string_type str() const &
Gets a copy of the underlying string object.
Definition: line_wrapping_stream.h:937
Stream buffer that wraps lines on white-space characters at the specified line length,...
Definition: line_wrapping_stream.h:42
size_t indent() const
Gets the current number of spaces that each line is indented with.
Definition: line_wrapping_stream.h:150
void swap(basic_line_wrapping_streambuf &other) noexcept
Swaps the contents basic_line_wrapping_streambuf instance with another.
Definition: line_wrapping_stream.h:204
void indent(size_t indent) noexcept
Sets the number of spaces that each line is indented with.
Definition: line_wrapping_stream.h:157
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:47
basic_line_wrapping_streambuf & operator=(basic_line_wrapping_streambuf &&other) noexcept
Move assignment operator.
Definition: line_wrapping_stream.h:77
void init(base_type *streambuf, size_t max_line_length, bool count_formatting=false) noexcept
Initializes this basic_line_wrapping_streambuf instance with the specified underlying stream buffer a...
Definition: line_wrapping_stream.h:103
virtual int sync() override
Flushes the buffer to the underlying stream buffer.
Definition: line_wrapping_stream.h:338
virtual int sync(bool flush_last_line)
Flushes the buffer to the underlying stream buffer, optionally including the the final,...
Definition: line_wrapping_stream.h:235
bool reset_indent()
Disables indentation for the next line.
Definition: line_wrapping_stream.h:171
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:268
typename base_type::char_type char_type
Character type used by the base type.
Definition: line_wrapping_stream.h:49
virtual void imbue(const std::locale &loc) override
Change the locale of the stream buffer.
Definition: line_wrapping_stream.h:345
std::basic_streambuf< CharType, Traits > base_type
The concrete type that this class derives from.
Definition: line_wrapping_stream.h:45
basic_line_wrapping_streambuf(basic_line_wrapping_streambuf &&other) noexcept
Move constructor.
Definition: line_wrapping_stream.h:71
typename base_type::traits_type traits_type
Traits type used by the base type.
Definition: line_wrapping_stream.h:51
virtual ~basic_line_wrapping_streambuf()
Destructor for the basic_line_wrapping_streambuf class.
Definition: line_wrapping_stream.h:89
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:680
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
details::flush_helper flush(bool flush_last_line)
IO manipulator that flushes a stream using a basic_line_wrapping_streambuf, optionally flushing the l...
Definition: line_wrapping_stream.h:719
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:658
short get_console_width(short default_width=80) noexcept
Determines the width of the console.
Definition: console_helper.h:19
Template to determine the correct console streams based on the character type.
Definition: console_helper.h:49
Provides types for using virtual terminal sequences with console output.