1// Boost.Range library
2//
3// Copyright Neil Groves 2007. Use, modification and
4// distribution is subject to the Boost Software License, Version
5// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6// http://www.boost.org/LICENSE_1_0.txt)
7//
8// For more information, see http://www.boost.org/libs/range/
9//
10
11#ifndef BOOST_RANGE_ADAPTOR_REPLACED_IMPL_HPP_INCLUDED
12#define BOOST_RANGE_ADAPTOR_REPLACED_IMPL_HPP_INCLUDED
13
14#include <boost/config.hpp>
15#include <boost/range/adaptor/argument_fwd.hpp>
16#include <boost/range/iterator_range.hpp>
17#include <boost/range/begin.hpp>
18#include <boost/range/end.hpp>
19#include <boost/range/value_type.hpp>
20#include <boost/range/concepts.hpp>
21#include <boost/iterator/iterator_adaptor.hpp>
22#include <boost/iterator/transform_iterator.hpp>
23#include <boost/optional/optional.hpp>
24
25namespace boost
26{
27 namespace range_detail
28 {
29 template< class Value >
30 class replace_value
31 {
32 public:
33 typedef const Value& result_type;
34 typedef const Value& first_argument_type;
35
36 // Rationale:
37 // The default constructor is required to allow the transform
38 // iterator to properly model the iterator concept.
39 replace_value()
40 {
41 }
42
43 replace_value(const Value& from, const Value& to)
44 : m_impl(data(from, to))
45 {
46 }
47
48 const Value& operator()(const Value& x) const
49 {
50 return (x == m_impl->m_from) ? m_impl->m_to : x;
51 }
52
53 private:
54 struct data
55 {
56 data(const Value& from, const Value& to)
57 : m_from(from)
58 , m_to(to)
59 {
60 }
61
62 Value m_from;
63 Value m_to;
64 };
65 boost::optional<data> m_impl;
66 };
67
68 template< class R >
69 class replaced_range :
70 public boost::iterator_range<
71 boost::transform_iterator<
72 replace_value< BOOST_DEDUCED_TYPENAME range_value<R>::type >,
73 BOOST_DEDUCED_TYPENAME range_iterator<R>::type > >
74 {
75 private:
76 typedef replace_value< BOOST_DEDUCED_TYPENAME range_value<R>::type > Fn;
77
78 typedef boost::iterator_range<
79 boost::transform_iterator<
80 replace_value< BOOST_DEDUCED_TYPENAME range_value<R>::type >,
81 BOOST_DEDUCED_TYPENAME range_iterator<R>::type > > base_t;
82
83 public:
84 typedef BOOST_DEDUCED_TYPENAME range_value<R>::type value_type;
85
86 replaced_range( R& r, value_type from, value_type to )
87 : base_t( make_transform_iterator( boost::begin(r), Fn(from, to) ),
88 make_transform_iterator( boost::end(r), Fn(from, to) ) )
89 { }
90 };
91
92 template< class T >
93 class replace_holder : public holder2<T>
94 {
95 public:
96 replace_holder( const T& from, const T& to )
97 : holder2<T>(from, to)
98 { }
99 private:
100 // not assignable
101 void operator=(const replace_holder&);
102 };
103
104 template< class SinglePassRange >
105 inline replaced_range<SinglePassRange>
106 operator|(
107 SinglePassRange& r,
108 const replace_holder<
109 BOOST_DEDUCED_TYPENAME range_value<SinglePassRange>::type>& f )
110 {
111 BOOST_RANGE_CONCEPT_ASSERT((
112 SinglePassRangeConcept<SinglePassRange>));
113
114 return replaced_range<SinglePassRange>(r, f.val1, f.val2);
115 }
116
117 template< class SinglePassRange >
118 inline replaced_range<const SinglePassRange>
119 operator|(
120 const SinglePassRange& r,
121 const replace_holder<
122 BOOST_DEDUCED_TYPENAME range_value<SinglePassRange>::type>& f)
123 {
124 BOOST_RANGE_CONCEPT_ASSERT((
125 SinglePassRangeConcept<const SinglePassRange>));
126
127 return replaced_range<const SinglePassRange>(r, f.val1, f.val2);
128 }
129 } // 'range_detail'
130
131 using range_detail::replaced_range;
132
133 namespace adaptors
134 {
135 namespace
136 {
137 const range_detail::forwarder2<range_detail::replace_holder>
138 replaced =
139 range_detail::forwarder2<range_detail::replace_holder>();
140 }
141
142 template<class SinglePassRange>
143 inline replaced_range<SinglePassRange>
144 replace(SinglePassRange& rng,
145 BOOST_DEDUCED_TYPENAME range_value<SinglePassRange>::type from,
146 BOOST_DEDUCED_TYPENAME range_value<SinglePassRange>::type to)
147 {
148 BOOST_RANGE_CONCEPT_ASSERT((
149 SinglePassRangeConcept<SinglePassRange>));
150
151 return replaced_range<SinglePassRange>(rng, from, to);
152 }
153
154 template<class SinglePassRange>
155 inline replaced_range<const SinglePassRange>
156 replace(const SinglePassRange& rng,
157 BOOST_DEDUCED_TYPENAME range_value<SinglePassRange>::type from,
158 BOOST_DEDUCED_TYPENAME range_value<SinglePassRange>::type to)
159 {
160 BOOST_RANGE_CONCEPT_ASSERT((
161 SinglePassRangeConcept<const SinglePassRange>));
162
163 return replaced_range<const SinglePassRange>(rng, from ,to);
164 }
165
166 } // 'adaptors'
167} // 'boost'
168
169#endif // include guard
170