libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/sound/step_iterator.hpp
Go to the documentation of this file.
00001 
00011 /*
00012  *  Copyright (C) 2010 Juan Pedro Bolivar Puente
00013  *
00014  *  This file is part of Psychosynth.
00015  *   
00016  *  Psychosynth is free software: you can redistribute it and/or modify
00017  *  it under the terms of the GNU General Public License as published by
00018  *  the Free Software Foundation, either version 3 of the License, or
00019  *  (at your option) any later version.
00020  *
00021  *  Psychosynth is distributed in the hope that it will be useful,
00022  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024  *  GNU General Public License for more details.
00025  *
00026  *  You should have received a copy of the GNU General Public License
00027  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00028  *
00029  */
00030 
00031 /*
00032  *  Copyright 2005-2007 Adobe Systems Incorporated
00033  * 
00034  *  Use, modification and distribution are subject to the Boost
00035  *  Software License, Version 1.0. (See accompanying file
00036  *  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
00037  */
00038 
00039 #ifndef GIL_STEP_ITERATOR_H
00040 #define GIL_STEP_ITERATOR_H
00041 
00042 #include <cstddef>
00043 #include <iterator>
00044 #include <boost/iterator/iterator_facade.hpp>
00045 
00046 #include <psynth/base/compat.hpp>
00047 #include <psynth/sound/util.hpp>
00048 #include <psynth/sound/frame_iterator.hpp>
00049 #include <psynth/sound/frame_iterator_adaptor.hpp>
00050 
00051 namespace psynth
00052 {
00053 namespace sound
00054 {
00055 
00063 namespace detail
00064 {
00065 
00077 template <typename Derived,  // type of the derived class
00078           typename Iterator, // Models Iterator
00079           typename SFn       // A policy object that can compute the
00080                              // distance between two iterators of type
00081                              // Iterator and can advance an iterator
00082                              // of type Iterator a given number of
00083                              // Iterator's units
00084           >
00085 class step_iterator_adaptor : public boost::iterator_adaptor<
00086     Derived, Iterator, boost::use_default, boost::use_default, boost::use_default,
00087     typename SFn::difference_type>
00088 {
00089 public:
00090     typedef boost::iterator_adaptor<Derived, Iterator,
00091                                     boost::use_default, boost::use_default,
00092                                     boost::use_default,
00093                                     typename SFn::difference_type> parent_type;
00094 
00095     typedef typename std::iterator_traits<Iterator>::difference_type
00096     base_difference_type;
00097     typedef typename SFn::difference_type  difference_type;
00098     typedef typename std::iterator_traits<Iterator>::reference reference;
00099 
00100     step_iterator_adaptor () {}
00101     
00102     step_iterator_adaptor (const Iterator& it, SFn step_fn = SFn ())
00103         : parent_type (it)
00104         , _step_fn (step_fn) {}
00105 
00106     difference_type step () const { return _step_fn.step(); }
00107 
00108 protected:
00109     SFn _step_fn;
00110 
00111 private:
00112     friend class boost::iterator_core_access;
00113 
00114     void increment ()
00115     { _step_fn.advance(this->base_reference(),1); }
00116 
00117     void decrement ()
00118     { _step_fn.advance(this->base_reference(),-1); }
00119 
00120     void advance (base_difference_type d)
00121     { _step_fn.advance(this->base_reference(),d); }
00122 
00123     difference_type distance_to(const step_iterator_adaptor& it) const
00124     {
00125         return _step_fn.difference (this->base_reference(),
00126                                     it.base_reference());
00127     }
00128 };
00129 
00135 template <typename D,typename Iterator,typename SFn> inline
00136 bool operator> (const step_iterator_adaptor<D,Iterator,SFn>& p1,
00137                  const step_iterator_adaptor<D,Iterator,SFn>& p2)
00138 { 
00139     return p1.step() > 0 ? p1.base() > p2.base() : p1.base() < p2.base(); 
00140 }
00141 
00142 template <typename D,typename Iterator,typename SFn> inline
00143 bool operator< (const step_iterator_adaptor<D,Iterator,SFn>& p1,
00144                  const step_iterator_adaptor<D,Iterator,SFn>& p2)
00145 { 
00146     return p1.step()>0 ? p1.base()< p2.base() : p1.base()> p2.base(); 
00147 }
00148 
00149 template <typename D,typename Iterator,typename SFn> inline
00150 bool operator>= (const step_iterator_adaptor<D,Iterator,SFn>& p1,
00151                   const step_iterator_adaptor<D,Iterator,SFn>& p2)
00152 { 
00153     return p1.step()>0 ? p1.base()>=p2.base() : p1.base()<=p2.base(); 
00154 }
00155 
00156 template <typename D,typename Iterator,typename SFn> inline
00157 bool operator<= (const step_iterator_adaptor<D,Iterator,SFn>& p1,
00158                  const step_iterator_adaptor<D,Iterator,SFn>& p2)
00159 { 
00160     return p1.step()>0 ? p1.base()<=p2.base() : p1.base()>=p2.base(); 
00161 }
00162 
00163 template <typename D,typename Iterator,typename SFn> inline
00164 bool operator== (const step_iterator_adaptor<D,Iterator,SFn>& p1,
00165                  const step_iterator_adaptor<D,Iterator,SFn>& p2)
00166 { 
00167     return p1.base()==p2.base(); 
00168 }
00169 
00170 template <typename D,typename Iterator,typename SFn> inline
00171 bool operator!= (const step_iterator_adaptor<D,Iterator,SFn>& p1,
00172                  const step_iterator_adaptor<D,Iterator,SFn>& p2)
00173 { 
00174     return p1.base()!=p2.base(); 
00175 }
00176 
00177 } /* namespace detail */
00178 
00179 
00180 /*
00181  *
00182  *                 MEMORY-BASED STEP ITERATOR
00183  *
00184  */
00185 
00218 template <typename Iterator>
00219 struct memunit_step_fn
00220 {
00221     typedef std::ptrdiff_t difference_type;
00222 
00223     memunit_step_fn (difference_type step = memunit_step (Iterator()))
00224         : _step (step) {}
00225 
00226     difference_type difference (const Iterator& it1, const Iterator& it2) const
00227     {
00228         return memunit_distance (it1,it2) / _step;
00229     }
00230 
00231     void advance (Iterator& it, difference_type d) const
00232     {
00233         memunit_advance (it, d * _step);
00234     }
00235     
00236     difference_type step () const { return _step; }
00237 
00238     void set_step (std::ptrdiff_t step) { _step = step; }
00239 
00240 private:
00241     PSYNTH_CLASS_REQUIRE(Iterator, psynth::sound, MemoryBasedIteratorConcept)
00242     difference_type _step;
00243 };
00244 
00245 template <typename Iterator>
00246 class memory_based_step_iterator :
00247     public detail::step_iterator_adaptor<memory_based_step_iterator<Iterator>, 
00248                                          Iterator, 
00249                                          memunit_step_fn<Iterator> >
00250 {
00251     PSYNTH_CLASS_REQUIRE(Iterator, psynth::sound, MemoryBasedIteratorConcept)
00252 
00253     public:
00254     typedef detail::step_iterator_adaptor<memory_based_step_iterator<Iterator>, 
00255                                           Iterator, 
00256                                           memunit_step_fn<Iterator> > parent_type;
00257     typedef typename parent_type::reference        reference;
00258     typedef typename parent_type::difference_type  difference_type;
00259     typedef Iterator                               base_iterator;
00260     
00261     memory_based_step_iterator ()
00262         : parent_type (Iterator()) {}
00263     memory_based_step_iterator (Iterator it, std::ptrdiff_t memunit_step)
00264         : parent_type(it, memunit_step_fn<Iterator>(memunit_step)) {}
00265 
00266     template <typename I2> 
00267     memory_based_step_iterator (const memory_based_step_iterator<I2>& it)
00268         : parent_type(it.base(), memunit_step_fn<Iterator>(it.step())) {}
00269 
00276     reference operator[] (difference_type d) const { return *(*this + d); }
00277 
00278     void set_step (std::ptrdiff_t memunit_step)
00279     { this->_step_fn.set_step (memunit_step); }
00280 
00281     base_iterator& base ()
00282     { return parent_type::base_reference (); }
00283 
00284     base_iterator const& base () const
00285     { return parent_type::base_reference (); }
00286 };
00287 
00288 template <typename Iterator>
00289 struct const_iterator_type<memory_based_step_iterator<Iterator> >
00290 {
00291     typedef memory_based_step_iterator<
00292         typename const_iterator_type<Iterator>::type>  type;
00293 };
00294 
00295 template <typename Iterator>
00296 struct iterator_is_mutable<memory_based_step_iterator<Iterator> >
00297     : public iterator_is_mutable<Iterator> {};
00298 
00299 
00300 /*
00301  *
00302  *    IteratorAdaptorConcept
00303  *
00304  */
00305 
00306 template <typename Iterator>
00307 struct is_iterator_adaptor<memory_based_step_iterator<Iterator> > :
00308     public boost::mpl::true_{};
00309 
00310 template <typename Iterator>
00311 struct iterator_adaptor_get_base<memory_based_step_iterator<Iterator> >
00312 {
00313     typedef Iterator type;
00314 };
00315 
00316 template <typename Iterator, typename NewBaseIterator>
00317 struct iterator_adaptor_rebind<memory_based_step_iterator<Iterator>,
00318                                NewBaseIterator>
00319 {
00320     typedef memory_based_step_iterator<NewBaseIterator> type;
00321 };
00322 
00323 
00324 /*
00325  *
00326  *    FrameBasedConcept
00327  *
00328  */
00329 
00330 template <typename Iterator>
00331 struct channel_space_type<memory_based_step_iterator<Iterator> > :
00332     public channel_space_type<Iterator> {};
00333 
00334 template <typename Iterator>
00335 struct sample_mapping_type<memory_based_step_iterator<Iterator> > :
00336     public sample_mapping_type<Iterator> {};
00337 
00338 template <typename Iterator>
00339 struct is_planar<memory_based_step_iterator<Iterator> > :
00340     public is_planar<Iterator> {};
00341 
00342 template <typename Iterator>
00343 struct sample_type<memory_based_step_iterator<Iterator> > :
00344     public sample_type<Iterator> {};
00345 
00346 /*
00347  *
00348  *    MemoryBasedIteratorConcept
00349  *
00350  */
00351 template <typename Iterator>
00352 struct byte_to_memunit<memory_based_step_iterator<Iterator> >
00353     : public byte_to_memunit<Iterator> {};
00354 
00355 template <typename Iterator>
00356 inline std::ptrdiff_t memunit_step (
00357     const memory_based_step_iterator<Iterator>& p) { return p.step(); }
00358 
00359 template <typename Iterator>
00360 inline std::ptrdiff_t memunit_distance (
00361     const memory_based_step_iterator<Iterator>& p1, 
00362     const memory_based_step_iterator<Iterator>& p2)
00363 { 
00364     return memunit_distance (p1.base(),p2.base()); 
00365 }
00366 
00367 template <typename Iterator>
00368 inline void memunit_advance (
00369     memory_based_step_iterator<Iterator>& p, 
00370     std::ptrdiff_t diff)
00371 { 
00372     memunit_advance (p.base(), diff);
00373 }
00374 
00375 template <typename Iterator>
00376 inline memory_based_step_iterator<Iterator> 
00377 memunit_advanced (
00378     const memory_based_step_iterator<Iterator>& p, 
00379     std::ptrdiff_t diff)
00380 {
00381     return memory_based_step_iterator<Iterator>(
00382         memunit_advanced(p.base(), diff),p.step());
00383 }
00384 
00385 template <typename Iterator>
00386 inline typename std::iterator_traits<Iterator>::reference 
00387 memunit_advanced_ref (
00388     const memory_based_step_iterator<Iterator>& p, 
00389     std::ptrdiff_t diff)
00390 { 
00391     return memunit_advanced_ref(p.base(), diff);
00392 }
00393 
00394 
00395 /*
00396  *
00397  *    HasDynamicStepTypeConcept
00398  *
00399  */
00400 
00401 template <typename Iterator>
00402 struct dynamic_step_type<memory_based_step_iterator<Iterator> >
00403 {
00404     typedef memory_based_step_iterator<Iterator> type;
00405 };
00406 
00407 /* For step iterators, pass the function object to the base */
00408 template <typename Iterator, typename Deref>
00409 struct iterator_add_deref<memory_based_step_iterator<Iterator>, Deref>
00410 {
00411     PSYNTH_CLASS_REQUIRE(Deref, psynth::sound, FrameDereferenceAdaptorConcept)
00412 
00413     typedef memory_based_step_iterator<
00414         typename iterator_add_deref<Iterator, Deref>::type> type;
00415 
00416     static type make (const memory_based_step_iterator<Iterator>& it,
00417                       const Deref& d)
00418     {
00419         return type (iterator_add_deref<Iterator, Deref>::make (
00420                          it.base(), d), it.step ());
00421     }
00422 };
00423 
00424 
00425 /*
00426  *
00427  *   make_step_iterator
00428  *
00429  */
00430 
00431 template <typename I>
00432 typename dynamic_step_type<I>::type
00433 make_step_iterator(const I& it, std::ptrdiff_t step);
00434 
00435 namespace detail
00436 {
00437 
00438 /* if the iterator is a plain base iterator (non-adaptor), wraps it in
00439    memory_based_step_iterator */
00440 template <typename I> 
00441 typename dynamic_step_type<I>::type make_step_iterator_impl (
00442     const I& it, std::ptrdiff_t step, boost::mpl::false_)
00443 {
00444     return memory_based_step_iterator<I> (it, step);
00445 }
00446 
00447 // If the iterator is compound, put the step in its base
00448 template <typename I> 
00449 typename dynamic_step_type<I>::type make_step_iterator_impl (
00450     const I& it, std::ptrdiff_t step, boost::mpl::true_)
00451 {
00452     return make_step_iterator (it.base (), step);
00453 }
00454 
00455 // If the iterator is memory_based_step_iterator, change the step
00456 template <typename BaseIt> 
00457 memory_based_step_iterator<BaseIt> make_step_iterator_impl(
00458     const memory_based_step_iterator<BaseIt>& it,
00459     std::ptrdiff_t step, boost::mpl::true_)
00460 {
00461     return memory_based_step_iterator<BaseIt> (it.base(), step);
00462 }
00463 }
00464 
00484 template <typename I>
00485 // Models MemoryBasedIteratorConcept, HasDynamicXStepTypeConcept
00486 typename dynamic_step_type<I>::type
00487 make_step_iterator (const I& it, std::ptrdiff_t step)
00488 {
00489     return detail::make_step_iterator_impl (
00490         it, step, typename is_iterator_adaptor<I>::type());
00491 }
00492 
00493 } /* namespace sound */
00494 } /* namespace psynth */
00495 
00496 #endif /* PSYNTH_SOUND_STEP_ITERATOR */