• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
25 namespace 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.
replace_value()39             replace_value()
40             {
41             }
42 
replace_value(const Value & from,const Value & to)43             replace_value(const Value& from, const Value& to)
44                 :   m_impl(data(from, to))
45             {
46             }
47 
operator ()(const Value & x) const48             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             {
databoost::range_detail::replace_value::data56                 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 
replaced_range(R & r,value_type from,value_type to)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:
replace_holder(const T & from,const T & to)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, class Value >
105         inline replaced_range<SinglePassRange>
operator |(SinglePassRange & r,const replace_holder<Value> & f)106         operator|(SinglePassRange& r, const replace_holder<Value>& f)
107         {
108             BOOST_RANGE_CONCEPT_ASSERT((
109                 SinglePassRangeConcept<SinglePassRange>));
110 
111             return replaced_range<SinglePassRange>(r, f.val1, f.val2);
112         }
113 
114         template< class SinglePassRange, class Value >
115         inline replaced_range<const SinglePassRange>
operator |(const SinglePassRange & r,const replace_holder<Value> & f)116         operator|(const SinglePassRange& r, const replace_holder<Value>& f)
117         {
118             BOOST_RANGE_CONCEPT_ASSERT((
119                 SinglePassRangeConcept<const SinglePassRange>));
120 
121             return replaced_range<const SinglePassRange>(r, f.val1, f.val2);
122         }
123     } // 'range_detail'
124 
125     using range_detail::replaced_range;
126 
127     namespace adaptors
128     {
129         namespace
130         {
131             const range_detail::forwarder2<range_detail::replace_holder>
132                 replaced =
133                     range_detail::forwarder2<range_detail::replace_holder>();
134         }
135 
136         template< class SinglePassRange, class Value >
137         inline replaced_range<SinglePassRange>
replace(SinglePassRange & rng,Value from,Value to)138         replace(SinglePassRange& rng, Value from, Value to)
139         {
140             BOOST_RANGE_CONCEPT_ASSERT((
141                 SinglePassRangeConcept<SinglePassRange>));
142 
143             return replaced_range<SinglePassRange>(rng, from, to);
144         }
145 
146         template< class SinglePassRange, class Value >
147         inline replaced_range<const SinglePassRange>
replace(const SinglePassRange & rng,Value from,Value to)148         replace(const SinglePassRange& rng, Value from, Value to)
149         {
150             BOOST_RANGE_CONCEPT_ASSERT((
151                 SinglePassRangeConcept<const SinglePassRange>));
152 
153             return replaced_range<const SinglePassRange>(rng, from ,to);
154         }
155 
156     } // 'adaptors'
157 } // 'boost'
158 
159 #endif // include guard
160