dune-common 2.1.1
arraylist.hh
Go to the documentation of this file.
00001 // $Id: arraylist.hh 6104 2010-08-24 17:20:45Z mblatt $
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   // forward declaration
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         
00178     inline void purge();
00179     
00183     inline void clear();
00187     ArrayList();
00188     
00189   private:
00190     
00194     typedef typename A::template rebind<shared_ptr<array<MemberType,chunkSize_> > >::other
00195     SmartPointerAllocator;
00196     
00200      typedef typename A::template rebind<array<MemberType,chunkSize_> >::other
00201      ArrayAllocator;
00202 
00206     friend class ArrayListIterator<T,N,A>;
00207     friend class ConstArrayListIterator<T,N,A>;
00208     
00210     std::vector<shared_ptr<array<MemberType,chunkSize_> >,
00211                 SmartPointerAllocator> chunks_;
00220     size_type capacity_;
00222     size_type size_;
00224     size_type start_;
00233     inline reference elementAt(size_type i);
00234     
00243     inline const_reference elementAt(size_type i) const;
00244   };
00245   
00246 
00250   template<class T, int N, class A>
00251   class ArrayListIterator : public RandomAccessIteratorFacade<ArrayListIterator<T,N,A>,
00252                                                               typename A::value_type,
00253                                                               typename A::reference,
00254                                                               typename A::difference_type>
00255   {
00256     
00257     friend class ArrayList<T,N,A>;
00258     friend class ConstArrayListIterator<T,N,A>;
00259   public:       
00263     typedef typename A::value_type MemberType;
00264     
00265     typedef typename A::difference_type difference_type;
00266     
00267     typedef typename A::size_type size_type;
00268     
00269     typedef typename A::reference reference;
00270     
00271     typedef typename A::const_reference const_reference;
00272     
00273     enum 
00274       { 
00280         chunkSize_ = (N > 0)? N : 1
00281       };
00282     
00283 
00289     inline bool equals(const ArrayListIterator<MemberType,N,A>& other)const;
00290     
00296     inline bool equals(const ConstArrayListIterator<MemberType,N,A>& other)const;
00297     
00301     inline void increment();
00302     
00306     inline void decrement();
00307     
00312     inline reference elementAt(size_type i)const;
00313     
00318     inline reference dereference()const;
00319     
00331     inline  void eraseToHere();
00332       
00334     inline size_type position(){return position_;}
00335     
00337     inline void advance(difference_type n);
00338     
00340     inline difference_type distanceTo(const ArrayListIterator<T,N,A>& other)const;
00341     
00343     inline ArrayListIterator<T,N,A>& operator=(const ArrayListIterator<T,N,A>& other);
00344     
00346     inline ArrayListIterator() : position_(0)
00347     {}
00348 
00349   private:
00355     inline ArrayListIterator(ArrayList<T,N,A>& arrayList, size_type position);
00356     
00360     size_type position_;
00364     ArrayList<T,N,A>* list_;
00365   };
00366   
00370   template<class T, int N, class A>
00371   class ConstArrayListIterator
00372     : public RandomAccessIteratorFacade<ConstArrayListIterator<T,N,A>, 
00373                                         const typename A::value_type,
00374                                         typename A::const_reference, 
00375                                         typename A::difference_type>
00376   {
00377 
00378     friend class ArrayList<T,N,A>;
00379     friend class ArrayListIterator<T,N,A>;
00380             
00381   public:       
00385     typedef typename A::value_type MemberType;
00386 
00387     typedef typename A::difference_type difference_type;
00388     
00389     typedef typename A::size_type size_type;
00390     
00391     typedef typename A::reference reference;
00392     
00393     typedef typename A::const_reference const_reference;
00394     enum 
00395       { 
00401         chunkSize_ = (N > 0)? N : 1
00402       };
00403 
00409     inline bool equals(const ConstArrayListIterator<MemberType,N,A>& other)const;
00410 
00414     inline void increment();
00415 
00419     inline void decrement();
00420       
00422     inline void advance(difference_type n);
00423 
00425     inline difference_type distanceTo(const ConstArrayListIterator<T,N,A>& other)const;
00426 
00431     inline const_reference elementAt(size_type i)const;
00432 
00437     inline const_reference dereference()const;
00438 
00439     inline const ConstArrayListIterator<T,N,A>& operator=(const ConstArrayListIterator<T,N,A>& other);
00440         
00441     inline ConstArrayListIterator() : position_(0)
00442     {}
00443 
00444     inline ConstArrayListIterator(const ArrayListIterator<T,N,A>& other);
00445 
00446   private:
00447 
00453     inline ConstArrayListIterator(const ArrayList<T,N,A>& arrayList, size_type position);
00454 
00458     size_type position_;
00462     const ArrayList<T,N,A>* list_;
00463   };
00464 
00465     
00466   template<class T, int N, class A>
00467   ArrayList<T,N,A>::ArrayList() 
00468     : capacity_(0), size_(0), start_(0)
00469   {
00470     chunks_.reserve(100);
00471   }
00472 
00473   template<class T, int N, class A>
00474   void ArrayList<T,N,A>::clear(){
00475     capacity_=0;
00476     size_=0;
00477     start_=0;
00478     chunks_.clear();
00479   }
00480 
00481   template<class T, int N, class A>
00482   size_t ArrayList<T,N,A>::size() const
00483   {
00484     return size_;
00485   }
00486 
00487   template<class T, int N, class A>
00488   void ArrayList<T,N,A>::push_back(const_reference entry)
00489   {
00490     size_t index=start_+size_;
00491     if(index==capacity_)
00492       {
00493         chunks_.push_back(shared_ptr<array<MemberType,chunkSize_> >(new array<MemberType,chunkSize_>()));
00494         capacity_ += chunkSize_;
00495       }
00496     elementAt(index)=entry;
00497     ++size_;
00498   }
00499 
00500   template<class T, int N, class A>
00501   typename ArrayList<T,N,A>::reference ArrayList<T,N,A>::operator[](size_type i)
00502   {
00503     return elementAt(start_+i);
00504   }
00505 
00506 
00507   template<class T, int N, class A>
00508   typename ArrayList<T,N,A>::const_reference ArrayList<T,N,A>::operator[](size_type i) const
00509   {
00510     return elementAt(start_+i);
00511   }
00512 
00513   template<class T, int N, class A>
00514   typename ArrayList<T,N,A>::reference ArrayList<T,N,A>::elementAt(size_type i)
00515   {
00516     return chunks_[i/chunkSize_]->operator[](i%chunkSize_);
00517   }
00518 
00519 
00520   template<class T, int N, class A>
00521   typename ArrayList<T,N,A>::const_reference ArrayList<T,N,A>::elementAt(size_type i) const
00522   {
00523     return chunks_[i/chunkSize_]->operator[](i%chunkSize_);
00524   }
00525 
00526   template<class T, int N, class A>
00527   ArrayListIterator<T,N,A> ArrayList<T,N,A>::begin()
00528   {
00529     return ArrayListIterator<T,N,A>(*this, start_);
00530   }
00531 
00532   template<class T, int N, class A>
00533   ConstArrayListIterator<T,N,A> ArrayList<T,N,A>::begin() const
00534   {
00535     return ConstArrayListIterator<T,N,A>(*this, start_);
00536   }
00537         
00538   template<class T, int N, class A>
00539   ArrayListIterator<T,N,A> ArrayList<T,N,A>::end()
00540   {
00541     return ArrayListIterator<T,N,A>(*this, start_+size_);
00542   }
00543 
00544   template<class T, int N, class A>
00545   ConstArrayListIterator<T,N,A> ArrayList<T,N,A>::end() const
00546   {
00547     return ConstArrayListIterator<T,N,A>(*this, start_+size_);
00548   }
00549 
00550   template<class T, int N, class A>
00551   void ArrayList<T,N,A>::purge()
00552   {
00553     // Distance to copy to the left.
00554     size_t distance = start_/chunkSize_;
00555     if(distance>0){
00556       // Number of chunks with entries in it;
00557       size_t chunks = ((start_%chunkSize_ + size_)/chunkSize_ );
00558       
00559       typedef typename std::vector<shared_ptr<array<MemberType,
00560         chunkSize_> > >::iterator iterator;
00561 
00562       // Copy chunks to the left.
00563       std::copy(chunks_.begin()+distance, 
00564                 chunks_.begin()+(distance+chunks), chunks_.begin());
00565 
00566       // Calculate new parameters
00567       start_ = start_ % chunkSize_;
00568       //capacity += distance * chunkSize_;
00569     }
00570   }
00571 
00572   template<class T, int N, class A>
00573   void ArrayListIterator<T,N,A>::advance(difference_type i)
00574   {
00575     position_+=i;
00576   }
00577 
00578   template<class T, int N, class A>
00579   void ConstArrayListIterator<T,N,A>::advance(difference_type i)
00580   {
00581     position_+=i;
00582   }
00583 
00584 
00585   template<class T, int N, class A>
00586   bool ArrayListIterator<T,N,A>::equals(const ArrayListIterator<MemberType,N,A>& other)const
00587   {
00588     // Makes only sense if we reference a common list
00589     assert(list_==(other.list_));
00590     return position_==other.position_ ;
00591   }
00592 
00593 
00594   template<class T, int N, class A>
00595   bool ArrayListIterator<T,N,A>::equals(const ConstArrayListIterator<MemberType,N,A>& other)const
00596   {
00597     // Makes only sense if we reference a common list
00598     assert(list_==(other.list_));
00599     return position_==other.position_ ;
00600   }
00601 
00602 
00603   template<class T, int N, class A>
00604   bool ConstArrayListIterator<T,N,A>::equals(const ConstArrayListIterator<MemberType,N,A>& other)const
00605   {
00606     // Makes only sense if we reference a common list
00607     assert(list_==(other.list_));
00608     return position_==other.position_ ;
00609   }
00610 
00611   template<class T, int N, class A>
00612   void ArrayListIterator<T,N,A>::increment()
00613   {
00614     ++position_;
00615   }
00616     
00617   template<class T, int N, class A>
00618   void ConstArrayListIterator<T,N,A>::increment()
00619   {
00620     ++position_;
00621   }
00622 
00623   template<class T, int N, class A>
00624   void  ArrayListIterator<T,N,A>::decrement()
00625   {
00626     --position_;
00627   }
00628 
00629   template<class T, int N, class A>
00630   void  ConstArrayListIterator<T,N,A>::decrement()
00631   {
00632     --position_;
00633   }
00634 
00635   template<class T, int N, class A>
00636   typename ArrayListIterator<T,N,A>::reference ArrayListIterator<T,N,A>::elementAt(size_type i) const 
00637   {
00638     return list_->elementAt(i+position_);
00639   }
00640 
00641   template<class T, int N, class A>
00642   typename ConstArrayListIterator<T,N,A>::const_reference ConstArrayListIterator<T,N,A>::elementAt(size_type i) const 
00643   {
00644     return list_->elementAt(i+position_);
00645   }
00646     
00647   template<class T, int N, class A>
00648   typename ArrayListIterator<T,N,A>::reference ArrayListIterator<T,N,A>::dereference() const
00649   {
00650     return list_->elementAt(position_);
00651   }
00652     
00653   template<class T, int N, class A>
00654   typename ConstArrayListIterator<T,N,A>::const_reference ConstArrayListIterator<T,N,A>::dereference() const
00655   {
00656     return list_->elementAt(position_);
00657   }
00658   
00659   template<class T, int N, class A>
00660   typename ArrayListIterator<T,N,A>::difference_type ArrayListIterator<T,N,A>::distanceTo(const ArrayListIterator<T,N,A>& other) const
00661   {
00662     // Makes only sense if we reference a common list
00663     assert(list_==(other.list_));
00664     return other.position_ - position_;
00665   }
00666 
00667   template<class T, int N, class A>
00668   typename ConstArrayListIterator<T,N,A>::difference_type ConstArrayListIterator<T,N,A>::distanceTo(const ConstArrayListIterator<T,N,A>& other) const
00669   {
00670     // Makes only sense if we reference a common list
00671     assert(list_==(other.list_));
00672     return other.position_ - position_;
00673   }
00674 
00675   template<class T, int N, class A>
00676   ArrayListIterator<T,N,A>& ArrayListIterator<T,N,A>::operator=(const ArrayListIterator<T,N,A>& other)
00677   {
00678     position_=other.position_;
00679     list_=other.list_;
00680     return *this;
00681   }
00682 
00683   template<class T, int N, class A>
00684   const ConstArrayListIterator<T,N,A>& ConstArrayListIterator<T,N,A>::operator=(const ConstArrayListIterator<T,N,A>& other)
00685   {
00686     position_=other.position_;
00687     list_=other.list_;
00688     return *this;
00689   }
00690 
00691   template<class T, int N, class A>
00692   void ArrayListIterator<T,N,A>::eraseToHere()
00693   {
00694     list_->size_ -= ++position_ - list_->start_;
00695     // chunk number of the new position.
00696     size_t posChunkStart = position_ / chunkSize_;
00697     // number of chunks to deallocate
00698     size_t chunks = (position_ - list_->start_ + list_->start_ % chunkSize_)
00699       / chunkSize_;
00700     list_->start_ = position_;
00701         
00702     // Deallocate memory not needed any more.
00703     for(size_t chunk=0; chunk<chunks;chunk++) {
00704         --posChunkStart;
00705         list_->chunks_[posChunkStart].reset();
00706     }
00707 
00708     // Capacity stays the same as the chunks before us
00709     // are still there. They null pointers.
00710     assert(list_->start_+list_->size_<=list_->capacity_);
00711   }
00712 
00713   template<class T, int N, class A>
00714   ArrayListIterator<T,N,A>::ArrayListIterator(ArrayList<T,N,A>& arrayList, size_type position) 
00715     : position_(position), list_(&arrayList)
00716   {}
00717 
00718     
00719   template<class T, int N, class A>
00720   ConstArrayListIterator<T,N,A>::ConstArrayListIterator(const ArrayList<T,N,A>& arrayList, 
00721                                                         size_type position) 
00722     : position_(position), list_(&arrayList)
00723   {}
00724 
00725   template<class T, int N, class A>
00726   ConstArrayListIterator<T,N,A>::ConstArrayListIterator(const ArrayListIterator<T,N,A>& other)
00727     : position_(other.position_), list_(other.list_)
00728   {}
00729 
00730     
00732 }
00733 #endif