• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2013 Francisco Jerez
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 // OTHER DEALINGS IN THE SOFTWARE.
21 //
22 
23 #ifndef CLOVER_UTIL_ADAPTOR_HPP
24 #define CLOVER_UTIL_ADAPTOR_HPP
25 
26 #include <iterator>
27 
28 #include "util/tuple.hpp"
29 #include "util/pointer.hpp"
30 #include "util/functional.hpp"
31 
32 namespace clover {
33    namespace detail {
34       ///
35       /// Implementation of the iterator concept that transforms the
36       /// value of the source iterators \a Is on dereference by use of
37       /// a functor \a F.
38       ///
39       /// The exact category of the resulting iterator should be the
40       /// least common denominator of the source iterator categories.
41       ///
42       template<typename F, typename... Is>
43       class iterator_adaptor {
44       public:
45          typedef std::forward_iterator_tag iterator_category;
46          typedef typename std::result_of<
47                F(typename std::iterator_traits<Is>::reference...)
48             >::type reference;
49          typedef typename std::remove_reference<reference>::type value_type;
50          typedef pseudo_ptr<value_type> pointer;
51          typedef std::ptrdiff_t difference_type;
52 
iterator_adaptor()53          iterator_adaptor() {
54          }
55 
iterator_adaptor(F f,std::tuple<Is...> && its)56          iterator_adaptor(F f, std::tuple<Is...> &&its) :
57             f(f), its(std::move(its)) {
58          }
59 
60          reference
operator *() const61          operator*() const {
62             return tuple::apply(f, tuple::map(derefs(), its));
63          }
64 
65          iterator_adaptor &
operator ++()66          operator++() {
67             tuple::map(preincs(), its);
68             return *this;
69          }
70 
71          iterator_adaptor
operator ++(int)72          operator++(int) {
73             auto jt = *this;
74             ++*this;
75             return jt;
76          }
77 
78          bool
operator ==(const iterator_adaptor & jt) const79          operator==(const iterator_adaptor &jt) const {
80             return its == jt.its;
81          }
82 
83          bool
operator !=(const iterator_adaptor & jt) const84          operator!=(const iterator_adaptor &jt) const {
85             return its != jt.its;
86          }
87 
88          pointer
operator ->() const89          operator->() const {
90             return { **this };
91          }
92 
93          iterator_adaptor &
operator --()94          operator--() {
95             tuple::map(predecs(), its);
96             return *this;
97          }
98 
99          iterator_adaptor
operator --(int)100          operator--(int) {
101             auto jt = *this;
102             --*this;
103             return jt;
104          }
105 
106          iterator_adaptor &
operator +=(difference_type n)107          operator+=(difference_type n) {
108             tuple::map(advances_by(n), its);
109             return *this;
110          }
111 
112          iterator_adaptor &
operator -=(difference_type n)113          operator-=(difference_type n) {
114             tuple::map(advances_by(-n), its);
115             return *this;
116          }
117 
118          iterator_adaptor
operator +(difference_type n) const119          operator+(difference_type n) const {
120             auto jt = *this;
121             jt += n;
122             return jt;
123          }
124 
125          iterator_adaptor
operator -(difference_type n) const126          operator-(difference_type n) const {
127             auto jt = *this;
128             jt -= n;
129             return jt;
130          }
131 
132          difference_type
operator -(const iterator_adaptor & jt) const133          operator-(const iterator_adaptor &jt) const {
134             return std::get<0>(its) - std::get<0>(jt.its);
135          }
136 
137          reference
operator [](difference_type n) const138          operator[](difference_type n) const {
139             return *(*this + n);
140          }
141 
142          bool
operator <(iterator_adaptor & jt) const143          operator<(iterator_adaptor &jt) const {
144             return *this - jt < 0;
145          }
146 
147          bool
operator >(iterator_adaptor & jt) const148          operator>(iterator_adaptor &jt) const {
149             return *this - jt > 0;
150          }
151 
152          bool
operator >=(iterator_adaptor & jt) const153          operator>=(iterator_adaptor &jt) const {
154             return !(*this < jt);
155          }
156 
157          bool
operator <=(iterator_adaptor & jt) const158          operator<=(iterator_adaptor &jt) const {
159             return !(*this > jt);
160          }
161 
162       protected:
163          F f;
164          std::tuple<Is...> its;
165       };
166 
167       template<typename F, typename... Is>
168       iterator_adaptor<F, Is...>
operator +(typename iterator_adaptor<F,Is...>::difference_type n,const iterator_adaptor<F,Is...> & jt)169       operator+(typename iterator_adaptor<F, Is...>::difference_type n,
170                 const iterator_adaptor<F, Is...> &jt) {
171          return (jt + n);
172       }
173 
174       template<typename F, typename... Is>
175       iterator_adaptor<F, Is...>
operator -(typename iterator_adaptor<F,Is...>::difference_type n,const iterator_adaptor<F,Is...> & jt)176       operator-(typename iterator_adaptor<F, Is...>::difference_type n,
177                 const iterator_adaptor<F, Is...> &jt) {
178          return (jt - n);
179       }
180    }
181 }
182 
183 #endif
184