ivl 679
ivl/details/array/impl/specialization/mask_class.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 
00025 namespace array_details {
00026 
00027 template<bool IS_CONTENT_RESIZEABLE>
00028 struct mask_tools
00029 {
00030         template<class A>
00031         static void shrink(A& a, size_t j) { }
00032 
00033         template<class A_IT, class B_IT>
00034         static size_t cut(A_IT a, B_IT b, B_IT b_end) { return 0; }
00035 };
00036 
00037 template<>
00038 struct mask_tools<true>
00039 {
00040         template<class A>
00041         static void shrink(A& a, size_t j)
00042         {
00043                  a.resize(a.length() - j);
00044         }
00045 
00046         template<class A_IT, class B_IT>
00047         static size_t cut(A_IT a, B_IT b, B_IT b_end);
00048 };
00049 
00050 template<class A_IT, class B_IT>
00051 size_t mask_tools<true>::cut(A_IT a, B_IT b, B_IT b_end)
00052 {
00053         size_t cut_size = 0;
00054 
00055         while(!*b && b != b_end) {
00056                 ++b;
00057                 ++a;
00058         }
00059         A_IT wa = a;
00060 
00061         while(1) {
00062                 while(b != b_end && *b) {
00063                         ++b;
00064                         ++a;
00065                         cut_size++;
00066                 }
00067                 if(b != b_end) {
00068                         *wa = *a;
00069                         ++wa;
00070                         ++a;
00071                 }
00072                 else
00073                         break;
00074         }
00075         return cut_size;
00076 }
00077 
00078 } /* namespace array_details */
00079 
00085 template <class T,
00086                  class A,
00087                  class B,
00088                  class DERIVED_INFO
00089              >
00090 class array<T, data::mask<A, B, DERIVED_INFO> >
00091         :
00092         public array_common_base<
00093                 array<T, data::mask<A, B, DERIVED_INFO> > >,
00094 
00095         public data::referer<typename types::derive<
00096                 array<T, data::mask<A, B, DERIVED_INFO> > >::type>
00097 {
00098 
00099 private:
00100         typedef array_common_base<array<T,
00101                 data::mask<A, B, DERIVED_INFO> > > common_base_class;
00102 
00103         typedef typename types::best_iterator<A>::type a_best_iterator;
00104 
00105         //TODO: need a simple redesign::
00106         //make b_begin iterator to point to the first EXISTANT element,
00107         //and then, do not allow before-begin access.
00108         //that was, past_end_capable will probably be unnecessary,
00109         //and if the access is precomputed on array creation,
00110         //it will (probably) be good. otherwise compute on any begin() call.
00111         //in any case it will not be slower and may be faster.
00112 
00113         //TODO: check if this is the best design::
00114         typedef auto_past_end_capable_iterator<
00115                 typename B::const_iterator> b_iterator;
00116         //typedef typename B::const_iterator b_iterator;
00117 
00118         // used to disable some types. TODO: test that not_a_type actually throws an error and
00119         // consider explicitly making the default constructor private.
00120         struct not_a_type { template<class X, class Y, class Z> not_a_type(X x, Y y, Z z); };
00121 
00122         typedef typename types::t_and_3<
00123                         types::t_not<types::is_const<A> >,
00124                         typename A::is_writeable,
00125                         typename A::is_resizeable>
00126                         ::type is_content_resizeable;
00127 
00128         typedef typename array_details::
00129                 mask_tools<array::is_content_resizeable::value> mask_tool;
00130 
00131         A* a;
00132         const B* b;
00133         a_best_iterator a_end;
00134         b_iterator b_end;
00135         ptrdiff_t len;
00136 
00137 protected:
00138         template <class J, class D>
00139         void copy_or_cut(const array<J, D>& o)
00140         {
00141                 if(is_content_resizeable::value && o.begin() == o.end() && len != 0) {
00142 
00143                         mask_tool::shrink(*a,
00144                                 mask_tool::cut(a->begin(), b.begin(), b_end));
00145                         b_end = b.begin();
00146                         len = 0;
00147 
00148                 } else {
00149                         static_cast<common_base_class&>(*this).assign_array(o);
00150                 }
00151         }
00152 
00153 public:
00154         typedef array this_type;
00155 
00156         typedef this_type this_array_type;
00157 
00158         typedef this_type array_type;
00159 
00160         typedef T elem_type;
00161 
00162         typedef typename a_best_iterator::reference best_reference;
00163         typedef typename a_best_iterator::reference reference;
00164         typedef typename A::const_iterator::reference const_reference;
00165 
00166         typedef typename types::derive<this_type>::type derived_type;
00167 
00168         typedef typename common_base_class::base_class base_class;
00169 
00171         typedef size_t size_type;
00172 
00173         using base_class::derived;
00174 
00175         struct iter_border_walker
00176         {
00177                 typename A::iter_border_walker iba;
00178                 typename B::iter_border_walker ibb;
00179                 bool first_to_last;
00180 
00181                 iter_border_walker() {}
00182                 iter_border_walker(ptrdiff_t) : iba(0), ibb(0), first_to_last(false) { }
00183                 template <class IT>
00184                 iter_border_walker(const IT& beg_it, const IT& end_it)
00185                 :
00186                 iba(data::iterator_extended_traits<typename IT::a_iterator>::
00187                                 get_iter_border_walker(beg_it.a, end_it.a)),
00188                 ibb(data::iterator_extended_traits<typename IT::b_iterator>::
00189                                 get_iter_border_walker(beg_it.b, end_it.b)),
00190                 first_to_last(false) { }
00191         };
00192 
00193         template <bool CONST>
00194         class iterator_type
00195         : public data::data_details::
00196                 iter_operator_expander<iterator_type<CONST>, T, CONST,
00197                         typename types::remove_const<
00198                                 typename a_best_iterator::reference>::type >,
00199                 public types::border_walker_iterator_identifier
00200         {
00201         private:
00202                 template <bool C> friend class iterator_type;
00203                 friend class array;
00204 
00205                 friend class iter_border_walker;
00206 
00207                 template <class X, class Y, bool C, class Z> 
00208                 friend class data::data_details::iter_operator_expander;
00209 
00210                 //friend class data::data_details::iter_operator_expander
00211                 //      <iterator_type<CONST>, T, CONST>;
00212 
00213                 typedef typename types::apply_const<T, types::t_expr<CONST> >
00214                         ::type best_value_type;
00215 
00216                 // this class is used to disable specific specialization members
00217                 class not_a_type { };
00218 
00219                 typedef typename types::t_if<types::t_expr<CONST>, not_a_type,
00220                         types::code_word<> >::type invalid_if_const;
00221 
00222                 typedef typename types::t_if<types::t_expr<CONST>,
00223                         typename A::const_iterator, typename 
00224                                 types::best_iterator<A>::type>::type a_iterator;
00225 
00226                 typedef typename a_iterator::reference prv_reference;
00227 
00228                 a_iterator a;
00229                 b_iterator b;
00230                 b_iterator b_end;
00231                 b_iterator b_rend;
00232 
00233         protected:
00234                 inline const_reference base(
00235                         types::code_word<> ok = types::code_word<>()) const
00236                         { return (*a); }
00237 
00238                 inline prv_reference base(
00239                         invalid_if_const disable = invalid_if_const())
00240                         { return (*a); }
00241 
00242         public:
00243                 typedef iterator_type<CONST> this_type;
00244 
00245                 // iterator_traits
00246                 typedef std::bidirectional_iterator_tag iterator_category;
00247                 typedef T value_type;
00248                 typedef typename types::apply_const<T, types::t_expr<CONST> >
00249                         ::type access_value_type;
00250                 typedef ptrdiff_t difference_type;
00251                 typedef access_value_type* pointer;
00252                 typedef typename a_iterator::reference reference;
00253 
00254                 // border walker
00255                 typedef typename array::iter_border_walker iter_border_walker;
00256 
00257                 // constructors
00258                 iterator_type() { }
00259 
00260                 iterator_type(const this_type& it)
00261                 : a(it.a), b(it.b), b_end(it.b_end), b_rend(it.b_rend) { }
00262 
00263                 template <bool C>
00264                 iterator_type(const iterator_type<C>& it)
00265                 : a(it.a), b(it.b), b_end(it.b_end), b_rend(it.b_rend) { }
00266 
00267                 iterator_type(const a_iterator& a, const b_iterator& b,
00268                         const b_iterator& b_end, const b_iterator& b_rend)
00269                         : a(a), b(b), b_end(b_end), b_rend(b_rend) { }
00270 
00271                 // members
00272 
00273                 // increment-decrement
00274                 this_type& operator++()
00275                 {
00276                         difference_type cnt = 1;
00277                         ++b;
00278                         while(b != b_end && !*b) { ++b; ++cnt; }
00279                         a += cnt;
00280                         return *this;
00281                 }
00282                 this_type& operator--()
00283                 {
00284                         difference_type cnt = 1;
00285                         --b;
00286                         while(b != b_rend && !*b) { --b; ++cnt; }
00287                         a -= cnt;
00288                         return *this;
00289                 }
00290 
00291                 this_type operator++(int) { this_type t(*this); ++(*this); return t; }
00292                 this_type operator--(int) { this_type t(*this); --(*this); return t; }
00293 
00294                 // += operator w/o random access. implemented only for (iterator + 1)
00295                 this_type& operator +=(size_t j)
00296                 {
00297                         CHECK(j == 1, ecomp);
00298                         ++(*this);
00299                         return *this;
00300                 }
00301                 this_type& operator -=(size_t j)
00302                 {
00303                         CHECK(j == 1, ecomp);
00304                         --(*this);
00305                         return *this;
00306                 }
00307                 inline this_type operator +(size_t j) const
00308                 {
00309                         CHECK(j == 1, ecomp);
00310                         this_type tmp(*this);
00311                         ++(*this);
00312                         return tmp;
00313                 }
00314                 inline this_type operator -(size_t j) const
00315                 {
00316                         CHECK(j == 1, ecomp);
00317                         this_type tmp(*this);
00318                         --(*this);
00319                         return tmp;
00320                 }
00321 
00322                 this_type& operator +=(iter_border_walker ib)
00323                 {
00324                         a += ib.iba;
00325                         b += ib.ibb;
00326                         if(ib.first_to_last) --(*this);
00327                         return *this;
00328                 }
00329                 this_type& operator -=(iter_border_walker ib)
00330                 {
00331                         a -= ib.iba;
00332                         b -= ib.ibb;
00333                         if(ib.first_to_last) ++(*this);
00334                         return *this;
00335                 }
00336                 inline this_type operator +(iter_border_walker j) const
00337                 {
00338                         this_type tmp(*this);
00339                         tmp += j;
00340                         return tmp;
00341                 }
00342                 inline this_type operator -(iter_border_walker j) const
00343                 {
00344                         this_type tmp(*this);
00345                         tmp -= j;
00346                         return tmp;
00347                 }
00348 
00349                 // difference is not implemented.
00350                 // this iterator is not random_access.
00351 
00352                 //copy same type iterator
00353                 this_type& operator=(const this_type& it)
00354                 {
00355                         a = it.a; b = it.b; b_end = it.b_end; b_rend = it.b_rend;
00356                         return *this;
00357                 }
00358                 //copy relevant type iterator
00359                 template<bool C>
00360                 this_type& operator=(const iterator_type<C>& it)
00361                 {
00362                         a = it.a; b = it.b; b_end = it.b_end; b_rend = it.b_rend;
00363                         return *this;
00364                 }
00365 
00366                 bool operator==(const this_type& it) const { return (b == it.b); }
00367                 bool operator!=(const this_type& it) const { return (b != it.b); }
00368                 bool operator<(const this_type& it) const { return (b < it.b); }
00369                 bool operator<=(const this_type& it) const { return (b <= it.b); }
00370                 bool operator>(const this_type& it) const { return (b > it.b); }
00371                 bool operator>=(const this_type& it) const { return (b >= it.b); }
00372 
00373                 //mask-specific. moves the iterator to the first valid position
00374                 this_type& stepfw()
00375                 {
00376                         difference_type cnt = 0;
00377                         while(b != b_end && !*b) { ++b; ++cnt; }
00378                         a += cnt;
00379                         return *this;
00380                 }
00381                 //meant to return reverse iterator
00382                 this_type& stepbk()
00383                 {
00384                         difference_type cnt = 0;
00385                         while(b != b_rend && !*b) { --b; ++cnt; }
00386                         a -= cnt;
00387                         return *this;
00388                 }
00389 
00390         };
00391 
00392         // typedefs for class iterators
00393         typedef typename types::t_if<typename array::is_writeable,
00394                 iterator_type<false>, not_a_type>::type iterator;
00395 
00396         typedef iterator_type<true> const_iterator;
00397 
00398         typedef typename types::t_if<typename array::is_writeable,
00399                 iterator, const_iterator>::type best_iterator;
00400 
00401         typedef typename types::t_if<typename array::is_writeable,
00402                 std::reverse_iterator<iterator>, not_a_type>::
00403                         type reverse_iterator;
00404 
00405         typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00406 
00407 
00408         iterator begin()
00409                 { return iterator(a->begin(), b->begin(),
00410                                                         b_end, b_iterator(b->begin()) - 1).stepfw(); }
00411 
00412         iterator end()
00413                 { return iterator(a_end, b_end, b_end, b_iterator(b->begin()) - 1); }
00414 
00415         const_iterator begin() const
00416                 { return const_iterator(a->begin(), b->begin(),
00417                                                                 b_end, b_iterator(b->begin()) - 1).stepfw(); }
00418 
00419         const_iterator end() const
00420                 { return const_iterator(a_end, b_end, b_end, 
00421                         b_iterator(b->begin()) - 1); }
00422 
00423         // reverse iterator defs
00424         reverse_iterator rbegin() { return reverse_iterator(end()); }
00425 
00426         reverse_iterator rend() { return reverse_iterator(begin()); }
00427 
00428         const_reverse_iterator rbegin() const
00429                 { return const_reverse_iterator(end()); }
00430 
00431         const_reverse_iterator rend() const
00432                 { return const_reverse_iterator(begin()); }
00433 
00436         //TODO: explain this better.
00439         size_t length() const
00440         {
00441                 if(this->len != -1)
00442                         return this->len;
00443 
00444                 size_t len = 0;
00445                 for(b_iterator bit = b->begin(); bit != b_end; bit++)
00446                         if(*bit)
00447                                 len++;
00448 
00449                 return len;
00450         }
00451         size_t length()
00452         {
00453                 if(this->len != -1)
00454                         return this->len;
00455 
00456                 size_t len = 0;
00457                 for(b_iterator bit = b->begin(); bit != b_end; bit++)
00458                         if(*bit)
00459                                 len++;
00460 
00461                 this->len = len;
00462                 return len;
00463         }
00465         size_type size() const { return length(); }
00466         size_type size() { return length(); }
00468         size_t numel() const { return length(); }
00469         size_t numel() { return length(); }
00470 
00471         void resize(size_t l)
00472         {
00473                 calc_length();
00474                 if(l == 0)
00475                         copy_or_cut(array<T, data::empty<> >());
00476                 else
00477                         CHECK(length() == l, ecomp);
00478         }
00479 
00480 
00486         this_type& calc_length() { len = length(); return *this; }
00490         iter_border_walker first_to_last() const
00491         {
00492                 iter_border_walker ib;
00493                 ib.iba = a->begin_to_end();
00494                 ib.ibb = b->begin_to_end();
00495                 ib.first_to_last = true;
00496                 return ib;
00497         }
00498         iter_border_walker begin_to_end() const
00499         {
00500                 iter_border_walker ib;
00501                 ib.iba = a->begin_to_end();
00502                 ib.ibb = b->begin_to_end();
00503                 ib.first_to_last = false;
00504                 return ib;
00505         }
00506 
00507         void init(A& a0, const B& b0)
00508         {
00509                 a = &a0;
00510                 b = &b0;
00511                 a_end = a0.end();
00512                 b_end = b0.end();
00513         }
00514 
00515         void init(const array& o)
00516         {
00517                 a = o.a;
00518                 b = o.b;
00519                 a_end = o.a_end;
00520                 b_end = o.b_end;
00521         }
00522 
00525 
00526         array(A& a, const B& b) : a(&a), b(&b), a_end(a.end()), b_end(b.end()),
00527                 len(-1)
00528         {
00529         }
00530 
00532         array(const this_type& o) : a(o.a), b(o.b), a_end(o.a_end), b_end(o.b_end),
00533                 len(o.len)
00534         {
00535         }
00536 
00539 
00540         ~array() { }
00541 
00542 
00545         template <class D>
00546         bool overlap(const D& d) const
00547         {
00548                 return a->overlap(d);
00549         }
00550 
00551         template <class D>
00552         bool self_overlap(const D& d) const
00553         {
00554                 return d.overlap(*a) || d.overlap(*b);
00555         }
00556 
00557         template <class J, class P>
00558         derived_type& assign_array(const array<J, data::empty<P> >& o)
00559         {
00560                 copy_or_cut(o); // will always fallback to cut
00561                 return this->derived();
00562         }
00563 
00564         template<class D>
00565         derived_type& assign_array(const D& o)
00566         {
00567                 copy_or_cut(o);
00568                 return this->derived();
00569         }
00570 
00576         using common_base_class::operator=;
00577 
00578         this_type& operator=(const this_type& o) // copy operator
00579         {
00580                 copy_or_cut(o);
00581                 return *this;
00582         }
00583 
00584 
00587 };
00588 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations