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 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