| // 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 |