Home | History | Annotate | Download | only in util
      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 
     53          iterator_adaptor() {
     54          }
     55 
     56          iterator_adaptor(F f, std::tuple<Is...> &&its) :
     57             f(f), its(std::move(its)) {
     58          }
     59 
     60          reference
     61          operator*() const {
     62             return tuple::apply(f, tuple::map(derefs(), its));
     63          }
     64 
     65          iterator_adaptor &
     66          operator++() {
     67             tuple::map(preincs(), its);
     68             return *this;
     69          }
     70 
     71          iterator_adaptor
     72          operator++(int) {
     73             auto jt = *this;
     74             ++*this;
     75             return jt;
     76          }
     77 
     78          bool
     79          operator==(const iterator_adaptor &jt) const {
     80             return its == jt.its;
     81          }
     82 
     83          bool
     84          operator!=(const iterator_adaptor &jt) const {
     85             return its != jt.its;
     86          }
     87 
     88          pointer
     89          operator->() const {
     90             return { **this };
     91          }
     92 
     93          iterator_adaptor &
     94          operator--() {
     95             tuple::map(predecs(), its);
     96             return *this;
     97          }
     98 
     99          iterator_adaptor
    100          operator--(int) {
    101             auto jt = *this;
    102             --*this;
    103             return jt;
    104          }
    105 
    106          iterator_adaptor &
    107          operator+=(difference_type n) {
    108             tuple::map(advances_by(n), its);
    109             return *this;
    110          }
    111 
    112          iterator_adaptor &
    113          operator-=(difference_type n) {
    114             tuple::map(advances_by(-n), its);
    115             return *this;
    116          }
    117 
    118          iterator_adaptor
    119          operator+(difference_type n) const {
    120             auto jt = *this;
    121             jt += n;
    122             return jt;
    123          }
    124 
    125          iterator_adaptor
    126          operator-(difference_type n) const {
    127             auto jt = *this;
    128             jt -= n;
    129             return jt;
    130          }
    131 
    132          difference_type
    133          operator-(const iterator_adaptor &jt) const {
    134             return std::get<0>(its) - std::get<0>(jt.its);
    135          }
    136 
    137          reference
    138          operator[](difference_type n) const {
    139             return *(*this + n);
    140          }
    141 
    142          bool
    143          operator<(iterator_adaptor &jt) const {
    144             return *this - jt < 0;
    145          }
    146 
    147          bool
    148          operator>(iterator_adaptor &jt) const {
    149             return *this - jt > 0;
    150          }
    151 
    152          bool
    153          operator>=(iterator_adaptor &jt) const {
    154             return !(*this < jt);
    155          }
    156 
    157          bool
    158          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...>
    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...>
    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