ivl 679
ivl/details/array/impl/specialization_details/ref_iterator/ref_iterator_tools.hpp
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations