ivl 679
|
00001 /* This file is part of the ivl C++ library <http://image.ntua.gr/ivl>. 00002 A C++ template library extending syntax towards mathematical notation. 00003 00004 Copyright (C) 2012 Yannis Avrithis <iavr@image.ntua.gr> 00005 Copyright (C) 2012 Kimon Kontosis <kimonas@image.ntua.gr> 00006 00007 ivl is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU Lesser General Public License 00009 version 3 as published by the Free Software Foundation. 00010 00011 Alternatively, you can redistribute it and/or modify it under the terms 00012 of the GNU General Public License version 2 as published by the Free 00013 Software Foundation. 00014 00015 ivl is distributed in the hope that it will be useful, 00016 but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00018 See the GNU General Public License for more details. 00019 00020 You should have received a copy of the GNU General Public License 00021 and a copy of the GNU Lesser General Public License along 00022 with ivl. If not, see <http://www.gnu.org/licenses/>. */ 00023 00024 #ifndef IVL_ARRAY_SPECIALIZATION_DETAILS_REF_ITERATOR_TOOLS_HPP 00025 #define IVL_ARRAY_SPECIALIZATION_DETAILS_REF_ITERATOR_TOOLS_HPP 00026 00027 namespace ivl { 00028 00029 namespace array_details { 00030 00031 template <class A, class IS_PTR_CAPABLE> 00032 struct ref_iterator_from_array_3 { }; 00033 00034 template <class A> 00035 struct ref_iterator_from_array_3<A, types::t_true> 00036 { 00037 typedef typename types::apply_const< 00038 typename A::elem_type, typename types::is_const<A>::type>::type *ptr_t; 00039 static inline ptr_t begin_raw(A& a) { return &*a.begin(); } //@@@@ 00040 static inline ptr_t end_raw(A& a) { return &*a.end(); } //@@@ changed to &* 00041 }; 00042 00043 template <class A> 00044 struct ref_iterator_from_array_3<A, types::t_false> 00045 { 00046 typedef typename types::apply_const< 00047 typename A::elem_type, typename types::is_const<A>::type>::type *ptr_t; 00048 static inline ptr_t begin_raw(A& a) { return a.c_ptr(); } 00049 static inline ptr_t end_raw(A& a) { return a.c_ptr() + a.length(); } 00050 }; 00051 00052 template <class A, class HAS_C_PTR> 00053 struct ref_iterator_from_array_2 { }; 00054 00055 template <class A> 00056 struct ref_iterator_from_array_2<A, types::t_true> 00057 : public ref_iterator_from_array_3<A, typename 00058 data::iterator_extended_traits<typename A::const_iterator> 00059 ::is_pointer_capable> 00060 { 00061 }; 00062 00063 template <class A> 00064 struct ref_iterator_from_array_2<A, types::t_false> 00065 { 00066 typedef typename types::best_iterator<A>::type ptr_t; 00067 static inline ptr_t begin_raw(A& a) { return a.begin(); } 00068 static inline ptr_t end_raw(A& a) { return a.end(); } 00069 }; 00070 00071 template <class A> 00072 struct ref_iterator_from_array_2<const A, types::t_false> 00073 { 00074 typedef typename A::const_iterator ptr_t; 00075 static inline ptr_t begin_raw(A& a) { return a.begin(); } 00076 static inline ptr_t end_raw(A& a) { return a.end(); } 00077 }; 00078 00079 // ----------------------------------------------------------- 00080 00081 // given a a reference of array type A, or const A, defines two methods, 00082 // begin_raw() and end_raw() which will try to get a pointer to begin() 00083 // instead of the begin() iterator if our ref_iterator array needs one 00084 template <class A, class NEED_PTR> 00085 struct ref_iterator_from_array { }; 00086 00087 template <class A> 00088 struct ref_iterator_from_array<A, types::t_true> : 00089 public ref_iterator_from_array_2<A, typename A::has_c_ptr> 00090 { }; 00091 00092 template <class A> 00093 struct ref_iterator_from_array<const A, types::t_true> : 00094 public ref_iterator_from_array_2<const A, typename A::has_c_ptr> 00095 { }; 00096 00097 template <class A> 00098 struct ref_iterator_from_array<A, types::t_false> : 00099 public ref_iterator_from_array_2<A, types::t_false> 00100 { }; 00101 00102 // ----------------------------------------------------------- 00103 00104 template <class K> 00105 struct ref_iterator_memmanage 00106 { 00107 typedef types::skip store_type; 00108 template<class T> 00109 static inline void destroy(store_type, T) { } 00110 }; 00111 00112 // ----------------------------------------------------------- 00113 00114 template <> 00115 struct ref_iterator_memmanage<ivl::data::deletable_c_ptr> 00116 { 00117 typedef bool store_type; 00118 template<class T> 00119 static inline void destroy(store_type b, T* ptr) 00120 { 00121 if(b) 00122 free((void*)ptr); 00123 } 00124 }; 00125 00126 // ----------------------------------------------------------- 00127 00128 template<class C, class CONST_IT> 00129 struct ref_iterator_add_const_it 00130 { 00131 private: 00132 const C& as_array() const { return static_cast<const C&>(*this); } 00133 public: 00134 typedef CONST_IT const_iterator; 00135 typedef std::reverse_iterator<CONST_IT> const_reverse_iterator; 00136 00137 const_iterator begin() const { return const_iterator(as_array().base_ptr); } 00138 const_iterator end() const 00139 { return const_iterator(as_array().get_it_end(as_array().end_iter)); } 00140 const_reverse_iterator rbegin() const { return end(); } 00141 const_reverse_iterator rend() const { return begin(); } 00142 }; 00143 00144 template<class C> 00145 struct ref_iterator_add_const_it<C, types::term> 00146 { 00147 class not_a_type{}; 00148 void begin(not_a_type) const {} 00149 void end(not_a_type) const {} 00150 void rbegin(not_a_type) const {} 00151 void rend(not_a_type) const {} 00152 }; 00153 00154 template<class C, class IT> 00155 struct ref_iterator_add_write_it 00156 { 00157 private: 00158 C& as_array() { return static_cast<C&>(*this); } 00159 public: 00160 typedef IT iterator; 00161 typedef std::reverse_iterator<IT> reverse_iterator; 00162 00163 iterator begin() 00164 { return iterator(as_array().base_ptr); } 00165 iterator end() 00166 { return iterator(as_array().get_it_end(as_array().end_iter)); } 00167 reverse_iterator rbegin() { return end(); } 00168 reverse_iterator rend() { return begin(); } 00169 }; 00170 00171 00172 template<class C> 00173 struct ref_iterator_add_write_it<C, types::term> 00174 { 00175 class not_a_type{}; 00176 void begin(not_a_type) {} 00177 void end(not_a_type) {} 00178 void rbegin(not_a_type) {} 00179 void rend(not_a_type) {} 00180 }; 00181 00182 template<class C, class CONST_IT, class HAS_RND_ACCESS> 00183 struct ref_iterator_add_const_rnd_op 00184 { 00185 private: 00186 const C& as_array() const { return static_cast<const C&>(*this); } 00187 protected: 00188 template <class X> 00189 static inline X rnd_add(const X& x, size_t y) { return x + y; } 00190 template <class X> 00191 static inline size_t rnd_sub(const X& x, const X& y) { return x - y; } 00192 public: 00194 typename std::iterator_traits<CONST_IT> 00195 ::reference operator[](size_t offset) const 00196 { 00197 CHECK(offset >= 0 && offset < as_array().length(), erange); 00198 return as_array().base_ptr[offset]; 00199 } 00200 }; 00201 00202 template<class C, class D> 00203 struct ref_iterator_add_const_nonrnd_op 00204 { 00205 protected: 00206 template <class X> 00207 static inline X rnd_add(X& x, size_t y) { return x; } 00208 template <class X> 00209 static inline size_t rnd_sub(const X& x, const X& y) { return 0; } 00210 public: 00211 class not_a_type{}; 00212 void operator[](not_a_type) const {} 00213 }; 00214 00215 template<class C, class D> 00216 struct ref_iterator_add_const_rnd_op<C, types::term, D> 00217 : public ref_iterator_add_const_nonrnd_op<C, D> { }; 00218 00219 template<class C, class D> 00220 struct ref_iterator_add_const_rnd_op<C, D, types::t_false> 00221 : public ref_iterator_add_const_nonrnd_op<C, D> { }; 00222 00223 00224 template<class C, class IT, class HAS_RND_ACCESS> 00225 struct ref_iterator_add_write_rnd_op 00226 { 00227 private: 00228 C& as_array() { return static_cast<C&>(*this); } 00229 public: 00231 typename std::iterator_traits<IT>::reference operator[](size_t offset) 00232 { 00233 CHECK(offset >= 0 && offset < as_array().length(), erange); 00234 return as_array().base_ptr[offset]; 00235 } 00236 }; 00237 00238 template<class C, class D> 00239 struct ref_iterator_add_write_rnd_op<C, types::term, D> 00240 { 00241 class not_a_type; 00242 void operator[](not_a_type) {} 00243 }; 00244 00245 template<class C, class D> 00246 struct ref_iterator_add_write_rnd_op<C, D, types::t_false> 00247 { 00248 class not_a_type; 00249 void operator[](not_a_type) {} 00250 }; 00251 00252 template <class ITER> 00253 struct ref_iterator_iter_traits 00254 { 00255 typedef typename std::iterator_traits<ITER> 00256 ::iterator_category iterator_category; 00257 00258 typedef typename std::iterator_traits<ITER>::reference reference; 00259 }; 00260 00261 template <> 00262 struct ref_iterator_iter_traits<types::term> 00263 { 00264 typedef types::term iterator_category; 00265 typedef types::term reference; 00266 }; 00267 00268 // class that gets information about the actual iterators 00269 // that are going to be used for the array. 00270 template <class IT, class CONST_IT, class T> 00271 struct ref_iterator_traits 00272 { 00273 protected: 00274 typedef typename types::t_or< 00275 types::t_and<types::t_eq<IT, types::term>, 00276 types::t_eq<CONST_IT, types::term> >, 00277 types::t_and< 00278 types::t_eq<IT, types::not_a_type>, 00279 types::t_eq<CONST_IT, types::term> > >:: 00280 type use_ptr; 00281 00282 typedef typename types::t_and< 00283 types::t_eq<IT, types::term>, types::t_eq<CONST_IT, types::term> > 00284 ::type both_term; 00285 00286 typedef typename types::t_if<use_ptr, typename types::t_if< 00287 both_term, T*, const T*>::type, IT>::type it; 00288 00289 typedef typename types::t_if<use_ptr, const T*, CONST_IT>::type const_it; 00290 00291 public: 00292 // -- wr_best_it 00293 typedef typename types::t_if<types::t_eq<it, types::term>, 00294 const_it, it>::type wr_best_itb; 00295 00296 typedef typename types::t_if<types::is_ivl_array<wr_best_itb>, 00297 wr_best_itb, ivl::array<int, data::empty<> > > 00298 ::type wr_best_ita; 00299 00300 typedef typename types::t_if<types::is_ivl_array<wr_best_itb>, 00301 typename types::best_iterator<wr_best_ita>::type, wr_best_itb> 00302 ::type wr_best_it; 00303 00304 typedef ref_iterator_iter_traits<wr_best_it> wr_best_traits; 00305 00306 typedef typename types::t_if< 00307 types::is_const<typename wr_best_traits::reference>, 00308 types::t_false, types::t_true>::type wr_has_write; 00309 00310 // -- wr_secondary_it 00311 typedef typename types::t_if<types::t_eq<it, types::term>, 00312 types::term, typename 00313 types::t_if<types::t_eq<it, const_it>, types::term, const_it>::type 00314 >::type wr_secondary_itb; 00315 00316 typedef typename types::t_if<types::t_and< 00317 types::is_ivl_array<wr_best_itb>, wr_has_write>, 00318 typename wr_best_ita::const_iterator, wr_secondary_itb> 00319 ::type wr_secondary_it; 00320 00321 typedef typename types::t_if<types::t_eq<types::term, wr_secondary_it>, 00322 wr_best_it, wr_secondary_it>::type wr_secondary_it_always_exist; 00323 00324 typedef ref_iterator_iter_traits<wr_secondary_it_always_exist> 00325 wr_secondary_traits; 00326 00327 // -- rest information 00328 typedef typename types::t_if<wr_has_write, 00329 wr_best_it, types::term>::type wr_write_it; 00330 00331 typedef typename types::t_if<wr_has_write, 00332 wr_secondary_it_always_exist, wr_best_it>::type wr_const_it; 00333 00334 typedef typename types::t_if<types::t_eq<wr_const_it, types::term>, 00335 types::t_false, types::t_true>::type wr_has_const; 00336 00337 typedef typename types::t_if< 00338 types::t_eq<typename wr_best_traits::iterator_category, 00339 std::random_access_iterator_tag>, 00340 types::t_true, types::t_false>::type 00341 wr_has_random_access; 00342 00343 }; 00344 00345 template <class C, class HAS_RND_ACCESS, class CONST_IT, class WRITE_IT> 00346 struct ref_iterator_extender_base : 00347 public 00348 ref_iterator_add_const_it<C, CONST_IT>, 00349 public 00350 ref_iterator_add_write_it<C, WRITE_IT>, 00351 public 00352 ref_iterator_add_const_rnd_op<C, CONST_IT, HAS_RND_ACCESS>, 00353 public 00354 ref_iterator_add_write_rnd_op<C, WRITE_IT, HAS_RND_ACCESS> 00355 { 00356 using ref_iterator_add_const_it<C, CONST_IT>::begin; 00357 using ref_iterator_add_const_it<C, CONST_IT>::end; 00358 using ref_iterator_add_const_it<C, CONST_IT>::rbegin; 00359 using ref_iterator_add_const_it<C, CONST_IT>::rend; 00360 using ref_iterator_add_write_it<C, WRITE_IT>::begin; 00361 using ref_iterator_add_write_it<C, WRITE_IT>::end; 00362 using ref_iterator_add_write_it<C, WRITE_IT>::rbegin; 00363 using ref_iterator_add_write_it<C, WRITE_IT>::rend; 00364 using ref_iterator_add_const_rnd_op<C, CONST_IT, HAS_RND_ACCESS> 00365 ::operator[]; 00366 using ref_iterator_add_write_rnd_op<C, WRITE_IT, HAS_RND_ACCESS> 00367 ::operator[]; 00368 }; 00369 00370 template < 00371 class C, 00372 class A, 00373 class PTR_RANGED_ITERS, 00374 class C_AND_A_HAS_CPTR, 00375 class C_REFERS_ARRAY, 00376 class DISABLE 00377 > 00378 struct ref_iterator_overlap 00379 { 00380 static inline bool overlap(const C& c, const A& a) { return false; } 00381 }; 00382 00383 template <class C, class A, class E, class F> 00384 struct ref_iterator_overlap<C, A, 00385 E, types::t_true, F, types::t_false> 00386 { 00387 // pointer region overlapping test. 00388 static inline bool overlap(const C& c, const A& a) 00389 { 00390 // simple pointer range intersection. 00391 ptrdiff_t d = c.c_ptr() - a.c_ptr(); 00392 return ((d > -ptrdiff_t(c.length())) && (d < ptrdiff_t(a.length()))); 00393 } 00394 }; 00395 00396 template <class C, class A, class E> 00397 struct ref_iterator_overlap<C, A, 00398 types::t_true, types::t_false, E, types::t_false> 00399 { 00400 static inline bool overlap(const C& c, const A& a) 00401 { 00402 // simple pointer range intersection. 00403 return &(*c.begin()) <= &(*a.end()) && &(*a.begin()) <= &(*c.end()); 00404 } 00405 }; 00406 00407 template <class C, class A> 00408 struct ref_iterator_overlap<C, A, 00409 types::t_false, types::t_false, types::t_true, types::t_false> 00410 { 00411 static inline bool overlap(const C& c, const A& a) 00412 { 00413 return c.begin().owner().overlap(a); 00414 } 00415 }; 00416 00417 template <class C, class A, class E, class F, class G> 00418 struct ref_iterator_overlap<C, A, E, F, G, types::t_false> 00419 { 00420 static inline bool overlap(const C& c, const A& a) 00421 { 00422 return false; 00423 } 00424 }; 00425 //--- 00426 00427 template <class C, class T, class HAS_C_PTR> struct ref_iterator_add_c_ptr { }; 00428 00429 template <class C, class T> 00430 struct ref_iterator_add_c_ptr<C, T*, types::t_true> 00431 { 00432 private: 00433 C& as_array() { return static_cast<C&>(*this); } 00434 const C& as_array() const { return static_cast<const C&>(*this); } 00435 public: 00436 typedef types::t_true has_c_ptr; 00437 T* c_ptr() { return &(*(as_array().begin())); } 00438 const T* c_ptr() const { return &(*(as_array().begin())); } 00439 }; 00440 00441 template <class C, class T> 00442 struct ref_iterator_add_c_ptr<C, const T*, types::t_true> 00443 { 00444 private: 00445 const C& as_array() const { return static_cast<const C&>(*this); } 00446 public: 00447 typedef types::t_true has_c_ptr; 00448 const T* c_ptr() const { return &(*(as_array().begin())); } 00449 }; 00450 00451 template <class C, class T> 00452 struct ref_iterator_add_c_ptr<C, T, types::t_false> 00453 { 00454 typedef types::t_false has_c_ptr; 00455 }; 00456 00457 template <class T> struct is_force_class 00458 : public types::t_false { }; 00459 00460 template <class A> 00461 struct is_force_class <data::wrap_array<A, data::force_wrap_array_attr> > 00462 : public types::t_true { }; 00463 00464 template <class C, class TR, class HAS_C_PTR> 00465 struct ref_iterator_add_c_ptr_and_overlap 00466 : 00467 public ref_iterator_add_c_ptr <C, 00468 typename std::iterator_traits<typename TR::wr_best_it>::pointer, 00469 typename types::t_or_3< 00470 types::is_ptr<typename TR::wr_best_it>, 00471 HAS_C_PTR, 00472 typename data::iterator_extended_traits<typename 00473 TR::wr_best_it>::is_pointer_based_and_contiguous 00474 >::type> 00475 { 00476 private: 00477 const C& as_array() const { return static_cast<const C&>(*this); } 00478 public: 00479 template <class A> 00480 bool overlap_array(const A& a) const 00481 { 00482 typedef typename std::iterator_traits<typename TR::wr_const_it> 00483 ::pointer c_pointer; 00484 typedef typename std::iterator_traits<typename A::const_iterator> 00485 ::pointer a_pointer; 00486 typedef typename types::t_eq<c_pointer, a_pointer>::type eq_p; 00487 00488 return ref_iterator_overlap<C, A, 00489 typename types::t_and_3<eq_p, 00490 typename data::iterator_extended_traits<typename 00491 TR::wr_const_it>::is_pointer_based, 00492 typename data::iterator_extended_traits<typename 00493 A::const_iterator>::is_pointer_based 00494 >::type, 00495 typename types::t_and_3<eq_p, 00496 typename ref_iterator_add_c_ptr_and_overlap::has_c_ptr, 00497 typename A::has_c_ptr>::type, 00498 typename data::iterator_extended_traits<typename TR::wr_const_it> 00499 ::is_array_reference_based, 00500 typename is_force_class<typename A::data_type>::type 00501 >::overlap(as_array(), a); 00502 } 00503 template <class J> 00504 bool overlap_element(const J& s) const 00505 { 00506 return false; 00507 } 00508 }; 00509 00510 // -------- 00511 00512 template <class C, class TR, class HAS_BORDER_WALKER> 00513 struct ref_iterator_add_border_walker { }; 00514 00515 template <class C, class TR> 00516 struct ref_iterator_add_border_walker<C, TR, types::t_false> 00517 { 00518 private: 00519 const C& as_array() const { return static_cast<const C&>(*this); } 00520 public: 00521 typedef ptrdiff_t iter_border_walker; 00522 iter_border_walker first_to_last() const { return as_array().length() - 1; } 00523 iter_border_walker begin_to_end() const { return as_array().length(); } 00524 }; 00525 00526 template <class C, class TR> 00527 struct ref_iterator_add_border_walker<C, TR, types::t_true> 00528 { 00529 private: 00530 const C& as_array() const { return static_cast<const C&>(*this); } 00531 typedef typename TR::wr_const_it it_store; 00532 public: 00533 typedef typename it_store::iter_border_walker iter_border_walker; 00534 iter_border_walker fist_to_last() const 00535 { 00536 it_store end_1 = as_array().end(); 00537 --end_1; 00538 return iter_border_walker(as_array().begin(), end_1); 00539 } 00540 iter_border_walker begin_to_end() const 00541 { 00542 return iter_border_walker(as_array().begin(), as_array().end()); 00543 } 00544 }; 00545 00546 // -------- 00547 00548 template <class C, class T, class IT, class CONST_IT, class HAS_C_PTR> 00549 struct ref_iterator_extender : 00550 00551 public 00552 ref_iterator_extender_base <C, 00553 typename ref_iterator_traits <IT, CONST_IT, T>::wr_has_random_access, 00554 typename ref_iterator_traits <IT, CONST_IT, T>::wr_const_it, 00555 typename ref_iterator_traits <IT, CONST_IT, T>::wr_write_it>, 00556 00557 public 00558 ref_iterator_add_c_ptr_and_overlap <C, ref_iterator_traits<IT, CONST_IT, T>, 00559 HAS_C_PTR>, 00560 00561 public 00562 ref_iterator_add_border_walker <C, ref_iterator_traits<IT, CONST_IT, T>, 00563 typename data::iterator_extended_traits<typename 00564 ref_iterator_traits<IT, CONST_IT, T>::wr_const_it> 00565 ::has_border_walker>, 00566 00567 protected 00568 ref_iterator_traits <IT, CONST_IT, T> 00569 { 00570 typedef ref_iterator_extender_base <C, 00571 typename ref_iterator_traits <IT, CONST_IT, T>::wr_has_random_access, 00572 typename ref_iterator_traits <IT, CONST_IT, T>::wr_const_it, 00573 typename ref_iterator_traits <IT, CONST_IT, T>::wr_write_it> ext; 00574 public: 00575 using ext::operator[]; 00576 using ext::begin; 00577 using ext::end; 00578 using ext::rbegin; 00579 using ext::rend; 00580 }; 00581 00582 } /* namespace array_details */ 00583 00584 } /* namespace ivl */ 00585 00586 #endif // IVL_ARRAY_SPECIALIZATION_DETAILS_REF_ITERATOR_TOOLS_HPP