00001
00002
00003 #ifndef DUNE_ARRAYLIST_HH
00004 #define DUNE_ARRAYLIST_HH
00005
00006 #include<cassert>
00007 #include<vector>
00008 #include"shared_ptr.hh"
00009 #include"array.hh"
00010 #include"iteratorfacades.hh"
00011
00012 namespace Dune
00013 {
00014
00015 template<class T, int N, class A>
00016 class ArrayListIterator;
00017
00018 template<class T, int N, class A>
00019 class ConstArrayListIterator;
00020
00055 template<class T, int N=100, class A=std::allocator<T> >
00056 class ArrayList
00057 {
00058 public:
00064 typedef T MemberType;
00065
00069 typedef T value_type;
00070
00074 typedef T& reference;
00075
00079 typedef const T& const_reference;
00080
00084 typedef T* pointer;
00085
00089 typedef const T* const_pointer;
00090
00091 enum
00092 {
00097 chunkSize_ = (N > 0)? N : 1
00098 };
00099
00103 typedef ArrayListIterator<MemberType,N,A> iterator;
00104
00108 typedef ConstArrayListIterator<MemberType,N,A> const_iterator;
00109
00113 typedef std::size_t size_type;
00114
00118 typedef std::ptrdiff_t difference_type;
00119
00124 iterator begin();
00125
00131 const_iterator begin() const;
00132
00137 iterator end();
00138
00143 const_iterator end() const;
00144
00149 inline void push_back(const_reference entry);
00150
00156 inline reference operator[](size_type i);
00157
00163 inline const_reference operator[](size_type i) const;
00164
00169 inline size_type size() const;
00170
00175 inline size_type capacity() const;
00176
00184 inline void purge();
00185
00189 inline void clear();
00193 ArrayList();
00194
00195 private:
00196
00200 typedef typename A::template rebind<shared_ptr<array<MemberType,chunkSize_> > >::other
00201 SmartPointerAllocator;
00202
00206 typedef typename A::template rebind<array<MemberType,chunkSize_> >::other
00207 ArrayAllocator;
00208
00212 friend class ArrayListIterator<T,N,A>;
00213 friend class ConstArrayListIterator<T,N,A>;
00214
00216 std::vector<shared_ptr<array<MemberType,chunkSize_> >,
00217 SmartPointerAllocator> chunks_;
00219 size_type capacity_;
00221 size_type size_;
00223 size_type start_;
00232 inline reference elementAt(size_type i);
00233
00242 inline const_reference elementAt(size_type i) const;
00243 };
00244
00245
00249 template<class T, int N, class A>
00250 class ArrayListIterator : public RandomAccessIteratorFacade<ArrayListIterator<T,N,A>,
00251 typename A::value_type,
00252 typename A::reference,
00253 typename A::difference_type>
00254 {
00255
00256 friend class ArrayList<T,N,A>;
00257 friend class ConstArrayListIterator<T,N,A>;
00258 public:
00262 typedef typename A::value_type MemberType;
00263
00264 typedef typename A::difference_type difference_type;
00265
00266 typedef typename A::size_type size_type;
00267
00268 typedef typename A::reference reference;
00269
00270 typedef typename A::const_reference const_reference;
00271
00272 enum
00273 {
00279 chunkSize_ = (N > 0)? N : 1
00280 };
00281
00282
00288 inline bool equals(const ArrayListIterator<MemberType,N,A>& other)const;
00289
00295 inline bool equals(const ConstArrayListIterator<MemberType,N,A>& other)const;
00296
00300 inline void increment();
00301
00305 inline void decrement();
00306
00311 inline reference elementAt(size_type i)const;
00312
00317 inline reference dereference()const;
00318
00330 inline void eraseToHere();
00331
00333 inline size_type position(){return position_;}
00334
00336 inline void advance(difference_type n);
00337
00339 inline difference_type distanceTo(const ArrayListIterator<T,N,A>& other)const;
00340
00342 inline ArrayListIterator<T,N,A>& operator=(const ArrayListIterator<T,N,A>& other);
00343
00345 inline ArrayListIterator() : position_(0)
00346 {}
00347
00348 private:
00354 inline ArrayListIterator(ArrayList<T,N,A>& arrayList, size_type position);
00355
00359 size_type position_;
00363 ArrayList<T,N,A>* list_;
00364 };
00365
00369 template<class T, int N, class A>
00370 class ConstArrayListIterator
00371 : public RandomAccessIteratorFacade<ConstArrayListIterator<T,N,A>,
00372 const typename A::value_type,
00373 typename A::const_reference,
00374 typename A::difference_type>
00375 {
00376
00377 friend class ArrayList<T,N,A>;
00378 friend class ArrayListIterator<T,N,A>;
00379
00380 public:
00384 typedef typename A::value_type MemberType;
00385
00386 typedef typename A::difference_type difference_type;
00387
00388 typedef typename A::size_type size_type;
00389
00390 typedef typename A::reference reference;
00391
00392 typedef typename A::const_reference const_reference;
00393 enum
00394 {
00400 chunkSize_ = (N > 0)? N : 1
00401 };
00402
00408 inline bool equals(const ConstArrayListIterator<MemberType,N,A>& other)const;
00409
00413 inline void increment();
00414
00418 inline void decrement();
00419
00421 inline void advance(difference_type n);
00422
00424 inline difference_type distanceTo(const ConstArrayListIterator<T,N,A>& other)const;
00425
00430 inline const_reference elementAt(size_type i)const;
00431
00436 inline const_reference dereference()const;
00437
00438 inline const ConstArrayListIterator<T,N,A>& operator=(const ConstArrayListIterator<T,N,A>& other);
00439
00440 inline ConstArrayListIterator() : position_(0)
00441 {}
00442
00443 inline ConstArrayListIterator(const ArrayListIterator<T,N,A>& other);
00444
00445 private:
00446
00452 inline ConstArrayListIterator(const ArrayList<T,N,A>& arrayList, size_type position);
00453
00457 size_type position_;
00461 const ArrayList<T,N,A>* list_;
00462 };
00463
00464
00465 template<class T, int N, class A>
00466 ArrayList<T,N,A>::ArrayList()
00467 : capacity_(0), size_(0), start_(0)
00468 {
00469 chunks_.reserve(100);
00470 }
00471
00472 template<class T, int N, class A>
00473 void ArrayList<T,N,A>::clear(){
00474 capacity_=0;
00475 size_=0;
00476 start_=0;
00477 chunks_.clear();
00478 }
00479
00480 template<class T, int N, class A>
00481 size_t ArrayList<T,N,A>::size() const
00482 {
00483 return size_;
00484 }
00485
00486 template<class T, int N, class A>
00487 size_t ArrayList<T,N,A>::capacity() const
00488 {
00489 return capacity_;
00490 }
00491
00492 template<class T, int N, class A>
00493 void ArrayList<T,N,A>::push_back(const_reference entry)
00494 {
00495 size_t index=start_+size_;
00496 if(index==capacity_)
00497 {
00498 chunks_.push_back(shared_ptr<array<MemberType,chunkSize_> >(new array<MemberType,chunkSize_>()));
00499 capacity_ += chunkSize_;
00500 }
00501 elementAt(index)=entry;
00502 ++size_;
00503 }
00504
00505 template<class T, int N, class A>
00506 typename ArrayList<T,N,A>::reference ArrayList<T,N,A>::operator[](size_type i)
00507 {
00508 return elementAt(start_+i);
00509 }
00510
00511
00512 template<class T, int N, class A>
00513 typename ArrayList<T,N,A>::const_reference ArrayList<T,N,A>::operator[](size_type i) const
00514 {
00515 return elementAt(start_+i);
00516 }
00517
00518 template<class T, int N, class A>
00519 typename ArrayList<T,N,A>::reference ArrayList<T,N,A>::elementAt(size_type i)
00520 {
00521 return chunks_[i/chunkSize_]->operator[](i%chunkSize_);
00522 }
00523
00524
00525 template<class T, int N, class A>
00526 typename ArrayList<T,N,A>::const_reference ArrayList<T,N,A>::elementAt(size_type i) const
00527 {
00528 return chunks_[i/chunkSize_]->operator[](i%chunkSize_);
00529 }
00530
00531 template<class T, int N, class A>
00532 ArrayListIterator<T,N,A> ArrayList<T,N,A>::begin()
00533 {
00534 return ArrayListIterator<T,N,A>(*this, start_);
00535 }
00536
00537 template<class T, int N, class A>
00538 ConstArrayListIterator<T,N,A> ArrayList<T,N,A>::begin() const
00539 {
00540 return ConstArrayListIterator<T,N,A>(*this, start_);
00541 }
00542
00543 template<class T, int N, class A>
00544 ArrayListIterator<T,N,A> ArrayList<T,N,A>::end()
00545 {
00546 return ArrayListIterator<T,N,A>(*this, start_+size_);
00547 }
00548
00549 template<class T, int N, class A>
00550 ConstArrayListIterator<T,N,A> ArrayList<T,N,A>::end() const
00551 {
00552 return ConstArrayListIterator<T,N,A>(*this, start_+size_);
00553 }
00554
00555 template<class T, int N, class A>
00556 void ArrayList<T,N,A>::purge()
00557 {
00558
00559 size_t distance = start_/chunkSize_;
00560 if(distance>0){
00561
00562 size_t chunks = ((start_%chunkSize_ + size_)/chunkSize_ );
00563
00564 typedef typename std::vector<shared_ptr<array<MemberType,
00565 chunkSize_> > >::iterator iterator;
00566
00567
00568 std::copy(chunks_.begin()+distance,
00569 chunks_.begin()+(distance+chunks), chunks_.begin());
00570
00571
00572 start_ = start_ % chunkSize_;
00573
00574 }
00575 }
00576
00577 template<class T, int N, class A>
00578 void ArrayListIterator<T,N,A>::advance(difference_type i)
00579 {
00580 position_+=i;
00581 }
00582
00583 template<class T, int N, class A>
00584 void ConstArrayListIterator<T,N,A>::advance(difference_type i)
00585 {
00586 position_+=i;
00587 }
00588
00589
00590 template<class T, int N, class A>
00591 bool ArrayListIterator<T,N,A>::equals(const ArrayListIterator<MemberType,N,A>& other)const
00592 {
00593
00594 assert(list_==(other.list_));
00595 return position_==other.position_ ;
00596 }
00597
00598
00599 template<class T, int N, class A>
00600 bool ArrayListIterator<T,N,A>::equals(const ConstArrayListIterator<MemberType,N,A>& other)const
00601 {
00602
00603 assert(list_==(other.list_));
00604 return position_==other.position_ ;
00605 }
00606
00607
00608 template<class T, int N, class A>
00609 bool ConstArrayListIterator<T,N,A>::equals(const ConstArrayListIterator<MemberType,N,A>& other)const
00610 {
00611
00612 assert(list_==(other.list_));
00613 return position_==other.position_ ;
00614 }
00615
00616 template<class T, int N, class A>
00617 void ArrayListIterator<T,N,A>::increment()
00618 {
00619 ++position_;
00620 }
00621
00622 template<class T, int N, class A>
00623 void ConstArrayListIterator<T,N,A>::increment()
00624 {
00625 ++position_;
00626 }
00627
00628 template<class T, int N, class A>
00629 void ArrayListIterator<T,N,A>::decrement()
00630 {
00631 --position_;
00632 }
00633
00634 template<class T, int N, class A>
00635 void ConstArrayListIterator<T,N,A>::decrement()
00636 {
00637 --position_;
00638 }
00639
00640 template<class T, int N, class A>
00641 typename ArrayListIterator<T,N,A>::reference ArrayListIterator<T,N,A>::elementAt(size_type i) const
00642 {
00643 return list_->elementAt(i+position_);
00644 }
00645
00646 template<class T, int N, class A>
00647 typename ConstArrayListIterator<T,N,A>::const_reference ConstArrayListIterator<T,N,A>::elementAt(size_type i) const
00648 {
00649 return list_->elementAt(i+position_);
00650 }
00651
00652 template<class T, int N, class A>
00653 typename ArrayListIterator<T,N,A>::reference ArrayListIterator<T,N,A>::dereference() const
00654 {
00655 return list_->elementAt(position_);
00656 }
00657
00658 template<class T, int N, class A>
00659 typename ConstArrayListIterator<T,N,A>::const_reference ConstArrayListIterator<T,N,A>::dereference() const
00660 {
00661 return list_->elementAt(position_);
00662 }
00663
00664 template<class T, int N, class A>
00665 typename ArrayListIterator<T,N,A>::difference_type ArrayListIterator<T,N,A>::distanceTo(const ArrayListIterator<T,N,A>& other) const
00666 {
00667
00668 assert(list_==(other.list_));
00669 return other.position_ - position_;
00670 }
00671
00672 template<class T, int N, class A>
00673 typename ConstArrayListIterator<T,N,A>::difference_type ConstArrayListIterator<T,N,A>::distanceTo(const ConstArrayListIterator<T,N,A>& other) const
00674 {
00675
00676 assert(list_==(other.list_));
00677 return other.position_ - position_;
00678 }
00679
00680 template<class T, int N, class A>
00681 ArrayListIterator<T,N,A>& ArrayListIterator<T,N,A>::operator=(const ArrayListIterator<T,N,A>& other)
00682 {
00683 position_=other.position_;
00684 list_=other.list_;
00685 return *this;
00686 }
00687
00688 template<class T, int N, class A>
00689 const ConstArrayListIterator<T,N,A>& ConstArrayListIterator<T,N,A>::operator=(const ConstArrayListIterator<T,N,A>& other)
00690 {
00691 position_=other.position_;
00692 list_=other.list_;
00693 return *this;
00694 }
00695
00696 template<class T, int N, class A>
00697 void ArrayListIterator<T,N,A>::eraseToHere()
00698 {
00699 list_->size_ -= ++position_ - list_->start_;
00700
00701 size_t posChunkStart = position_ / chunkSize_;
00702
00703 size_t chunks = (position_ - list_->start_ + list_->start_ % chunkSize_)
00704 / chunkSize_;
00705 list_->start_ = position_;
00706
00707
00708 for(size_t chunk=0; chunk<chunks;chunk++) {
00709 --posChunkStart;
00710 assert(list_->chunks_[posChunkStart] && list_->chunks_[posChunkStart].use_count()==1);
00711 list_->chunks_[posChunkStart].reset();
00712 }
00713
00714
00715 list_->capacity_-=chunks*chunkSize_;
00716 }
00717
00718 template<class T, int N, class A>
00719 ArrayListIterator<T,N,A>::ArrayListIterator(ArrayList<T,N,A>& arrayList, size_type position)
00720 : position_(position), list_(&arrayList)
00721 {}
00722
00723
00724 template<class T, int N, class A>
00725 ConstArrayListIterator<T,N,A>::ConstArrayListIterator(const ArrayList<T,N,A>& arrayList,
00726 size_type position)
00727 : position_(position), list_(&arrayList)
00728 {}
00729
00730 template<class T, int N, class A>
00731 ConstArrayListIterator<T,N,A>::ConstArrayListIterator(const ArrayListIterator<T,N,A>& other)
00732 : position_(other.position_), list_(other.list_)
00733 {}
00734
00735
00737 }
00738 #endif