Modules | Alphabetical List | Class List | Directories | File List | File Members | GIL Home Page # step_iterator.hpp Go to the documentation of this file.
    00001 /*
    00002     Copyright 2005-2007 Adobe Systems Incorporated
    00003
    00004     Use, modification and distribution are subject to the Boost Software License,
    00005     Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
    00006     http://www.boost.org/LICENSE_1_0.txt).
    00007
    00008     See http://opensource.adobe.com/gil for most recent version including documentation.
    00009 */
    00010
    00011 /*************************************************************************************************/
    00012
    00013 #ifndef GIL_STEP_ITERATOR_H
    00014 #define GIL_STEP_ITERATOR_H
    00015
    00024
    00025 #include <cstddef>
    00026 #include <iterator>
    00027 #include <boost/iterator/iterator_facade.hpp>
    00028 #include "gil_config.hpp"
    00029 #include "utilities.hpp"
    00030 #include "pixel_iterator.hpp"
    00031 #include "pixel_iterator_adaptor.hpp"
    00032
    00033 namespace boost { namespace gil {
    00034
    00038
    00039
    00040 namespace detail {
    00041
    00048
    00049 template <typename Derived,  // type of the derived class
    00050           typename Iterator, // Models Iterator
    00051           typename SFn>      // A policy object that can compute the distance between two iterators of type Iterator
    00052                              // and can advance an iterator of type Iterator a given number of Iterator's units
    00053 class step_iterator_adaptor : public iterator_adaptor<Derived, Iterator, use_default, use_default, use_default, typename SFn::difference_type> {
    00054 public:
    00055     typedef iterator_adaptor<Derived, Iterator, use_default, use_default, use_default, typename SFn::difference_type> parent_t;
    00056     typedef typename std::iterator_traits<Iterator>::difference_type base_difference_type;
    00057     typedef typename SFn::difference_type                           difference_type;
    00058     typedef typename std::iterator_traits<Iterator>::reference       reference;
    00059
    00060     step_iterator_adaptor() {}
    00061     step_iterator_adaptor(const Iterator& it, SFn step_fn=SFn()) : parent_t(it), _step_fn(step_fn) {}
    00062
    00063     difference_type step() const { return _step_fn.step(); }
    00064
    00065 protected:
    00066     SFn _step_fn;
    00067 private:
    00068     friend class boost::iterator_core_access;
    00069
    00070     void increment() { _step_fn.advance(this->base_reference(),1); }
    00071     void decrement() { _step_fn.advance(this->base_reference(),-1); }
    00072     void advance(base_difference_type d) { _step_fn.advance(this->base_reference(),d); }
    00073     difference_type distance_to(const step_iterator_adaptor& it) const { return _step_fn.difference(this->base_reference(),it.base_reference()); }
    00074 };
    00075
    00076 // although iterator_adaptor defines these, the default implementation computes distance and compares for zero.
    00077 // it is often faster to just apply the relation operator to the base
    00078 template <typename D,typename Iterator,typename SFn> inline
    00079 bool operator>(const step_iterator_adaptor<D,Iterator,SFn>& p1, const step_iterator_adaptor<D,Iterator,SFn>& p2) {
    00080     return p1.step()>0 ? p1.base()> p2.base() : p1.base()< p2.base();
    00081 }
    00082
    00083 template <typename D,typename Iterator,typename SFn> inline
    00084 bool operator<(const step_iterator_adaptor<D,Iterator,SFn>& p1, const step_iterator_adaptor<D,Iterator,SFn>& p2) {
    00085     return p1.step()>0 ? p1.base()< p2.base() : p1.base()> p2.base();
    00086 }
    00087
    00088 template <typename D,typename Iterator,typename SFn> inline
    00089 bool operator>=(const step_iterator_adaptor<D,Iterator,SFn>& p1, const step_iterator_adaptor<D,Iterator,SFn>& p2) {
    00090     return p1.step()>0 ? p1.base()>=p2.base() : p1.base()<=p2.base();
    00091 }
    00092
    00093 template <typename D,typename Iterator,typename SFn> inline
    00094 bool operator<=(const step_iterator_adaptor<D,Iterator,SFn>& p1, const step_iterator_adaptor<D,Iterator,SFn>& p2) {
    00095     return p1.step()>0 ? p1.base()<=p2.base() : p1.base()>=p2.base();
    00096 }
    00097
    00098 template <typename D,typename Iterator,typename SFn> inline
    00099 bool operator==(const step_iterator_adaptor<D,Iterator,SFn>& p1, const step_iterator_adaptor<D,Iterator,SFn>& p2) {
    00100     return p1.base()==p2.base();
    00101 }
    00102
    00103 template <typename D,typename Iterator,typename SFn> inline
    00104 bool operator!=(const step_iterator_adaptor<D,Iterator,SFn>& p1, const step_iterator_adaptor<D,Iterator,SFn>& p2) {
    00105     return p1.base()!=p2.base();
    00106 }
    00107
    00108 } // namespace detail
    00109
    00113
    00129
    00132 template <typename Iterator>
    00133 struct memunit_step_fn {
    00134     typedef std::ptrdiff_t difference_type;
    00135
    00136     memunit_step_fn(difference_type step=memunit_step(Iterator())) : _step(step) {}
    00137
    00138     difference_type difference(const Iterator& it1, const Iterator& it2) const { return memunit_distance(it1,it2)/_step; }
    00139     void            advance(Iterator& it, difference_type d)             const { memunit_advance(it,d*_step); }
    00140     difference_type step()                                               const { return _step; }
    00141
    00142     void            set_step(std::ptrdiff_t step) { _step=step; }
    00143 private:
    00144     GIL_CLASS_REQUIRE(Iterator, boost::gil, MemoryBasedIteratorConcept);
    00145     difference_type _step;
    00146 };
    00147
    00148 template <typename Iterator>
    00149 class memory_based_step_iterator : public detail::step_iterator_adaptor<memory_based_step_iterator<Iterator>,
    00150                                                                             Iterator,
    00151                                                                             memunit_step_fn<Iterator> > {
    00152     GIL_CLASS_REQUIRE(Iterator, boost::gil, MemoryBasedIteratorConcept);
    00153 public:
    00154     typedef detail::step_iterator_adaptor<memory_based_step_iterator<Iterator>,
    00155                                           Iterator,
    00156                                           memunit_step_fn<Iterator> > parent_t;
    00157     typedef typename parent_t::reference                            reference;
    00158     typedef typename parent_t::difference_type                      difference_type;
    00159     typedef Iterator                                                x_iterator;
    00160
    00161     memory_based_step_iterator() : parent_t(Iterator()) {}
    00162     memory_based_step_iterator(Iterator it, std::ptrdiff_t memunit_step) : parent_t(it, memunit_step_fn<Iterator>(memunit_step)) {}
    00163     template <typename I2>
    00164     memory_based_step_iterator(const memory_based_step_iterator<I2>& it)
    00165         : parent_t(it.base(), memunit_step_fn<Iterator>(it.step())) {}
    00166
    00169     reference operator[](difference_type d) const { return *(*this+d); }
    00170
    00171     void set_step(std::ptrdiff_t memunit_step) { this->_step_fn.set_step(memunit_step); }
    00172
    00173     x_iterator& base()              { return parent_t::base_reference(); }
    00174     x_iterator const& base() const  { return parent_t::base_reference(); }
    00175 };
    00176
    00177 template <typename Iterator>
    00178 struct const_iterator_type<memory_based_step_iterator<Iterator> > {
    00179     typedef memory_based_step_iterator<typename const_iterator_type<Iterator>::type>  type;
    00180 };
    00181
    00182 template <typename Iterator>
    00183 struct iterator_is_mutable<memory_based_step_iterator<Iterator> > : public iterator_is_mutable<Iterator> {};
    00184
    00185
    00187 //  IteratorAdaptorConcept
    00189
    00190 template <typename Iterator>
    00191 struct is_iterator_adaptor<memory_based_step_iterator<Iterator> > : public mpl::true_{};
    00192
    00193 template <typename Iterator>
    00194 struct iterator_adaptor_get_base<memory_based_step_iterator<Iterator> > {
    00195     typedef Iterator type;
    00196 };
    00197
    00198 template <typename Iterator, typename NewBaseIterator>
    00199 struct iterator_adaptor_rebind<memory_based_step_iterator<Iterator>,NewBaseIterator> {
    00200     typedef memory_based_step_iterator<NewBaseIterator> type;
    00201 };
    00202
    00204 //  PixelBasedConcept
    00206
    00207 template <typename Iterator>
    00208 struct color_space_type<memory_based_step_iterator<Iterator> > : public color_space_type<Iterator> {};
    00209
    00210 template <typename Iterator>
    00211 struct channel_mapping_type<memory_based_step_iterator<Iterator> > : public channel_mapping_type<Iterator> {};
    00212
    00213 template <typename Iterator>
    00214 struct is_planar<memory_based_step_iterator<Iterator> > : public is_planar<Iterator> {};
    00215
    00216 template <typename Iterator>
    00217 struct channel_type<memory_based_step_iterator<Iterator> > : public channel_type<Iterator> {};
    00218
    00220 //  MemoryBasedIteratorConcept
    00222 template <typename Iterator>
    00223 struct byte_to_memunit<memory_based_step_iterator<Iterator> > : public byte_to_memunit<Iterator> {};
    00224
    00225 template <typename Iterator>
    00226 inline std::ptrdiff_t memunit_step(const memory_based_step_iterator<Iterator>& p) { return p.step(); }
    00227
    00228 template <typename Iterator>
    00229 inline std::ptrdiff_t memunit_distance(const memory_based_step_iterator<Iterator>& p1,
    00230                                     const memory_based_step_iterator<Iterator>& p2) {
    00231     return memunit_distance(p1.base(),p2.base());
    00232 }
    00233
    00234 template <typename Iterator>
    00235 inline void memunit_advance(memory_based_step_iterator<Iterator>& p,
    00236                          std::ptrdiff_t diff) {
    00237     memunit_advance(p.base(), diff);
    00238 }
    00239
    00240 template <typename Iterator>
    00241 inline memory_based_step_iterator<Iterator>
    00242 memunit_advanced(const memory_based_step_iterator<Iterator>& p,
    00243               std::ptrdiff_t diff) {
    00244     return memory_based_step_iterator<Iterator>(memunit_advanced(p.base(), diff),p.step());
    00245 }
    00246
    00247 template <typename Iterator>
    00248 inline typename std::iterator_traits<Iterator>::reference
    00249 memunit_advanced_ref(const memory_based_step_iterator<Iterator>& p,
    00250                   std::ptrdiff_t diff) {
    00251     return memunit_advanced_ref(p.base(), diff);
    00252 }
    00253
    00255 //  HasDynamicXStepTypeConcept
    00257
    00258 template <typename Iterator>
    00259 struct dynamic_x_step_type<memory_based_step_iterator<Iterator> > {
    00260     typedef memory_based_step_iterator<Iterator> type;
    00261 };
    00262
    00263 // For step iterators, pass the function object to the base
    00264 template <typename Iterator, typename Deref>
    00265 struct iterator_add_deref<memory_based_step_iterator<Iterator>,Deref> {
    00266     GIL_CLASS_REQUIRE(Deref, boost::gil, PixelDereferenceAdaptorConcept);
    00267
    00268     typedef memory_based_step_iterator<typename iterator_add_deref<Iterator, Deref>::type> type;
    00269
    00270     static type make(const memory_based_step_iterator<Iterator>& it, const Deref& d) { return type(iterator_add_deref<Iterator, Deref>::make(it.base(),d),it.step()); }
    00271 };
    00272
    00276
    00277 template <typename I> typename dynamic_x_step_type<I>::type make_step_iterator(const I& it, std::ptrdiff_t step);
    00278
    00279 namespace detail {
    00280
    00281 // if the iterator is a plain base iterator (non-adaptor), wraps it in memory_based_step_iterator
    00282 template <typename I>
    00283 typename dynamic_x_step_type<I>::type make_step_iterator_impl(const I& it, std::ptrdiff_t step, mpl::false_) {
    00284     return memory_based_step_iterator<I>(it, step);
    00285 }
    00286
    00287 // If the iterator is compound, put the step in its base
    00288 template <typename I>
    00289 typename dynamic_x_step_type<I>::type make_step_iterator_impl(const I& it, std::ptrdiff_t step, mpl::true_) {
    00290     return make_step_iterator(it.base(), step);
    00291 }
    00292
    00293 // If the iterator is memory_based_step_iterator, change the step
    00294 template <typename BaseIt>
    00295 memory_based_step_iterator<BaseIt> make_step_iterator_impl(const memory_based_step_iterator<BaseIt>& it, std::ptrdiff_t step, mpl::true_) {
    00296     return memory_based_step_iterator<BaseIt>(it.base(), step);
    00297 }
    00298 }
    00299
    00313 template <typename I>  // Models MemoryBasedIteratorConcept, HasDynamicXStepTypeConcept
    00314 typename dynamic_x_step_type<I>::type make_step_iterator(const I& it, std::ptrdiff_t step) {
    00315     return detail::make_step_iterator_impl(it, step, typename is_iterator_adaptor<I>::type());
    00316 }
    00317
    00318 } }  // namespace boost::gil
    00319
    00320 #endif