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