|
libpsynth 0.2.1
|
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 */
1.7.4