228 lines
6.1 KiB
C++
228 lines
6.1 KiB
C++
/// \file
|
|
// Range v3 library
|
|
//
|
|
// Copyright Eric Niebler 2014-present
|
|
//
|
|
// Use, modification and distribution is subject to the
|
|
// Boost Software License, Version 1.0. (See accompanying
|
|
// file LICENSE_1_0.txt or copy at
|
|
// http://www.boost.org/LICENSE_1_0.txt)
|
|
//
|
|
// Project home: https://github.com/ericniebler/range-v3
|
|
//
|
|
#ifndef RANGES_V3_ITERATOR_STREAM_ITERATORS_HPP
|
|
#define RANGES_V3_ITERATOR_STREAM_ITERATORS_HPP
|
|
|
|
#include <cstddef>
|
|
#include <iosfwd>
|
|
#include <iterator>
|
|
#include <string>
|
|
#include <type_traits>
|
|
#include <utility>
|
|
|
|
#include <range/v3/range_fwd.hpp>
|
|
|
|
#include <range/v3/iterator/concepts.hpp>
|
|
|
|
#include <range/v3/detail/prologue.hpp>
|
|
|
|
namespace ranges
|
|
{
|
|
/// \addtogroup group-iterator
|
|
/// @{
|
|
template<typename T = void, typename Char = char,
|
|
typename Traits = std::char_traits<Char>>
|
|
struct ostream_iterator
|
|
{
|
|
private:
|
|
template<class U>
|
|
using value_t = meta::if_<std::is_void<T>, U, T>;
|
|
|
|
public:
|
|
using difference_type = std::ptrdiff_t;
|
|
using char_type = Char;
|
|
using traits_type = Traits;
|
|
using ostream_type = std::basic_ostream<Char, Traits>;
|
|
|
|
constexpr ostream_iterator() = default;
|
|
ostream_iterator(ostream_type & s, Char const * d = nullptr) noexcept
|
|
: sout_(&s)
|
|
, delim_(d)
|
|
{}
|
|
template(typename U)(
|
|
/// \pre
|
|
requires convertible_to<U, value_t<U> const &>)
|
|
ostream_iterator & operator=(U && value)
|
|
{
|
|
RANGES_EXPECT(sout_);
|
|
*sout_ << static_cast<value_t<U> const &>(static_cast<U &&>(value));
|
|
if(delim_)
|
|
*sout_ << delim_;
|
|
return *this;
|
|
}
|
|
ostream_iterator & operator*()
|
|
{
|
|
return *this;
|
|
}
|
|
ostream_iterator & operator++()
|
|
{
|
|
return *this;
|
|
}
|
|
ostream_iterator & operator++(int)
|
|
{
|
|
return *this;
|
|
}
|
|
|
|
private:
|
|
ostream_type * sout_;
|
|
Char const * delim_;
|
|
};
|
|
|
|
template<typename Delim, typename Char = char,
|
|
typename Traits = std::char_traits<Char>>
|
|
struct ostream_joiner
|
|
{
|
|
CPP_assert(semiregular<Delim>);
|
|
using difference_type = std::ptrdiff_t;
|
|
using char_type = Char;
|
|
using traits_type = Traits;
|
|
using ostream_type = std::basic_ostream<Char, Traits>;
|
|
|
|
constexpr ostream_joiner() = default;
|
|
ostream_joiner(ostream_type & s, Delim const & d)
|
|
: delim_(d)
|
|
, sout_(std::addressof(s))
|
|
, first_(true)
|
|
{}
|
|
ostream_joiner(ostream_type & s, Delim && d)
|
|
: delim_(std::move(d))
|
|
, sout_(std::addressof(s))
|
|
, first_(true)
|
|
{}
|
|
template<typename T>
|
|
ostream_joiner & operator=(T const & value)
|
|
{
|
|
RANGES_EXPECT(sout_);
|
|
if(!first_)
|
|
*sout_ << delim_;
|
|
first_ = false;
|
|
*sout_ << value;
|
|
return *this;
|
|
}
|
|
ostream_joiner & operator*() noexcept
|
|
{
|
|
return *this;
|
|
}
|
|
ostream_joiner & operator++() noexcept
|
|
{
|
|
return *this;
|
|
}
|
|
ostream_joiner & operator++(int) noexcept
|
|
{
|
|
return *this;
|
|
}
|
|
|
|
private:
|
|
Delim delim_;
|
|
ostream_type * sout_;
|
|
bool first_;
|
|
};
|
|
|
|
struct make_ostream_joiner_fn
|
|
{
|
|
template(typename Delim, typename Char, typename Traits)(
|
|
/// \pre
|
|
requires semiregular<detail::decay_t<Delim>>)
|
|
ostream_joiner<detail::decay_t<Delim>, Char, Traits> //
|
|
operator()(std::basic_ostream<Char, Traits> & s, Delim && d) const
|
|
{
|
|
return {s, std::forward<Delim>(d)};
|
|
}
|
|
};
|
|
|
|
/// \sa `make_ostream_joiner_fn`
|
|
RANGES_INLINE_VARIABLE(make_ostream_joiner_fn, make_ostream_joiner)
|
|
|
|
template<typename Char, typename Traits = std::char_traits<Char>>
|
|
struct ostreambuf_iterator
|
|
{
|
|
public:
|
|
typedef ptrdiff_t difference_type;
|
|
typedef Char char_type;
|
|
typedef Traits traits_type;
|
|
typedef std::basic_streambuf<Char, Traits> streambuf_type;
|
|
typedef std::basic_ostream<Char, Traits> ostream_type;
|
|
|
|
constexpr ostreambuf_iterator() = default;
|
|
ostreambuf_iterator(ostream_type & s) noexcept
|
|
: ostreambuf_iterator(s.rdbuf())
|
|
{}
|
|
ostreambuf_iterator(streambuf_type * s) noexcept
|
|
: sbuf_(s)
|
|
{
|
|
RANGES_ASSERT(s != nullptr);
|
|
}
|
|
ostreambuf_iterator & operator=(Char c)
|
|
{
|
|
RANGES_ASSERT(sbuf_ != nullptr);
|
|
if(!failed_)
|
|
failed_ = (sbuf_->sputc(c) == Traits::eof());
|
|
return *this;
|
|
}
|
|
ostreambuf_iterator & operator*()
|
|
{
|
|
return *this;
|
|
}
|
|
ostreambuf_iterator & operator++()
|
|
{
|
|
return *this;
|
|
}
|
|
ostreambuf_iterator & operator++(int)
|
|
{
|
|
return *this;
|
|
}
|
|
bool failed() const noexcept
|
|
{
|
|
return failed_;
|
|
}
|
|
|
|
private:
|
|
streambuf_type * sbuf_ = nullptr;
|
|
bool failed_ = false;
|
|
};
|
|
|
|
namespace cpp20
|
|
{
|
|
template<typename T, typename Char = char,
|
|
typename Traits = std::char_traits<Char>>
|
|
using ostream_iterator = ranges::ostream_iterator<T, Char, Traits>;
|
|
|
|
using ranges::ostreambuf_iterator;
|
|
} // namespace cpp20
|
|
/// @}
|
|
} // namespace ranges
|
|
|
|
/// \cond
|
|
RANGES_DIAGNOSTIC_PUSH
|
|
RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
|
|
|
|
namespace std
|
|
{
|
|
template<typename T, typename Char, typename Traits>
|
|
struct iterator_traits<::ranges::ostream_iterator<T, Char, Traits>>
|
|
: ::ranges::detail::std_output_iterator_traits<>
|
|
{};
|
|
|
|
template<typename Char, typename Traits>
|
|
struct iterator_traits<::ranges::ostreambuf_iterator<Char, Traits>>
|
|
: ::ranges::detail::std_output_iterator_traits<>
|
|
{};
|
|
} // namespace std
|
|
|
|
RANGES_DIAGNOSTIC_POP
|
|
/// \endcond
|
|
|
|
#include <range/v3/detail/epilogue.hpp>
|
|
|
|
#endif // RANGES_V3_ITERATOR_STREAM_ITERATORS_HPP
|