blob: f31f1bceb255abfd866bf2593aa6b622687b8b62 [file] [log] [blame]
// Boost.Range library
//
// Copyright Neil Groves 2014.
// 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)
//
// For more information, see http://www.boost.org/libs/range/
//
#ifndef BOOST_RANGE_ADAPTOR_FORMATTED_HPP_INCLUDED
#define BOOST_RANGE_ADAPTOR_FORMATTED_HPP_INCLUDED
#include <boost/config.hpp>
#include <boost/range/concepts.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/iterator.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_array.hpp>
#include <boost/type_traits/remove_extent.hpp>
#include <ostream>
namespace boost
{
namespace range_detail
{
template<typename Sep, typename Prefix, typename Postfix>
struct formatted_holder
{
typedef typename boost::mpl::if_<
boost::is_array<Sep>,
const typename boost::remove_extent<Sep>::type*,
Sep
>::type separator_t;
typedef typename boost::mpl::if_<
boost::is_array<Prefix>,
const typename boost::remove_extent<Prefix>::type*,
Prefix
>::type prefix_t;
typedef typename boost::mpl::if_<
boost::is_array<Postfix>,
const typename boost::remove_extent<Postfix>::type*,
Postfix
>::type postfix_t;
formatted_holder(
const separator_t& sep,
const prefix_t& prefix,
const postfix_t& postfix)
: m_sep(sep)
, m_prefix(prefix)
, m_postfix(postfix)
{
}
separator_t m_sep;
prefix_t m_prefix;
postfix_t m_postfix;
};
template<typename Iter, typename Sep, typename Prefix, typename Postfix>
class formatted_range
: public boost::iterator_range<Iter>
{
typedef formatted_holder<Sep,Prefix,Postfix> holder_t;
public:
formatted_range(Iter first, Iter last, const holder_t& holder)
: boost::iterator_range<Iter>(first, last)
, m_holder(holder)
{
}
template<typename OStream>
void write(OStream& out) const
{
Iter it(this->begin());
out << m_holder.m_prefix;
if (it != this->end())
{
out << *it;
for (++it; it != this->end(); ++it)
{
out << m_holder.m_sep << *it;
}
}
out << m_holder.m_postfix;
}
private:
holder_t m_holder;
};
template<
typename SinglePassRange,
typename Sep,
typename Prefix,
typename Postfix
>
inline range_detail::formatted_range<
typename range_iterator<const SinglePassRange>::type, Sep, Prefix, Postfix
>
operator|(
const SinglePassRange& rng,
const range_detail::formatted_holder<Sep,Prefix,Postfix>& holder
)
{
typedef typename range_iterator<const SinglePassRange>::type iterator;
return range_detail::formatted_range<iterator, Sep, Prefix, Postfix>(
boost::begin(rng), boost::end(rng), holder);
}
template<typename Char, typename Traits, typename Iter, typename Sep,
typename Prefix, typename Postfix>
std::basic_ostream<Char, Traits>&
operator<<(
std::basic_ostream<Char, Traits>& out,
const formatted_range<Iter, Sep, Prefix, Postfix>& writer)
{
writer.write(out);
return out;
}
} // namespace range_detail
namespace adaptors
{
template<typename Sep, typename Prefix, typename Postfix>
range_detail::formatted_holder<Sep, Prefix, Postfix>
formatted(const Sep& sep, const Prefix& prefix, const Postfix& postfix)
{
return range_detail::formatted_holder<Sep,Prefix,Postfix>(
sep, prefix, postfix);
}
template<typename Sep, typename Prefix>
range_detail::formatted_holder<Sep, Prefix, char>
formatted(const Sep& sep, const Prefix& prefix)
{
return range_detail::formatted_holder<Sep, Prefix, char>(sep, prefix, '}');
}
template<typename Sep>
range_detail::formatted_holder<Sep, char, char>
formatted(const Sep& sep)
{
return range_detail::formatted_holder<Sep, char, char>(sep, '{', '}');
}
inline range_detail::formatted_holder<char, char, char>
formatted()
{
return range_detail::formatted_holder<char, char, char>(',', '{', '}');
}
using range_detail::formatted_range;
template<typename SinglePassRange, typename Sep, typename Prefix,
typename Postfix>
inline boost::range_detail::formatted_range<
typename boost::range_iterator<const SinglePassRange>::type,
Sep, Prefix, Postfix
>
format(
const SinglePassRange& rng,
const Sep& sep,
const Prefix& prefix,
const Postfix& postfix
)
{
typedef typename boost::range_iterator<const SinglePassRange>::type
iterator_t;
typedef boost::range_detail::formatted_range<
iterator_t, Sep, Prefix, Postfix> result_t;
typedef boost::range_detail::formatted_holder<Sep, Prefix, Postfix>
holder_t;
return result_t(boost::begin(rng), boost::end(rng),
holder_t(sep, prefix, postfix));
}
template<typename SinglePassRange, typename Sep, typename Prefix>
inline boost::range_detail::formatted_range<
typename boost::range_iterator<const SinglePassRange>::type,
Sep, Prefix, char
>
format(
const SinglePassRange& rng,
const Sep& sep,
const Prefix& prefix)
{
return adaptors::format<SinglePassRange, Sep, Prefix, char>(rng, sep, prefix, '}');
}
template<typename SinglePassRange, typename Sep>
inline boost::range_detail::formatted_range<
typename boost::range_iterator<const SinglePassRange>::type,
Sep, char, char
>
format(const SinglePassRange& rng, const Sep& sep)
{
return adaptors::format<SinglePassRange, Sep, char, char>(rng, sep, '{', '}');
}
template<typename SinglePassRange>
inline boost::range_detail::formatted_range<
typename boost::range_iterator<const SinglePassRange>::type,
char, char, char
>
format(const SinglePassRange& rng)
{
return adaptors::format<SinglePassRange, char, char, char>(rng, ',', '{', '}');
}
} // namespace adaptors
namespace range
{
using boost::range_detail::formatted_range;
} // namespace range
} // namespace boost
#endif // include guard