Main Page | Compound List | File List | Compound Members

rvec.h

00001 /* -*- c++ -*- */
00002 /*
00003  * A vector class template allowing gaps
00004  *
00005  * Copyright (C) 2004 Oskar Enoksson (enok@lysator.liu.se)
00006  *
00007  * This program is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  
00020  */
00021 #ifndef RPTR_RVEC_HDR
00022 #define RPTR_RVEC_HDR
00023 
00024 #include "rptr.h"
00025 
00026 #include <vector>
00027 #include <stdexcept>
00028 
00029 namespace rptr {
00031 
00053   template<class T>
00054   class Rvec {
00055   public:
00056     typedef T value_type;
00057   private:
00058     struct Node {
00059       Rptr<T> ptr;
00060       typename std::vector<Node>::difference_type prev;
00061       typename std::vector<Node>::difference_type next;
00062       Node(): prev(0), next(0) {}
00063     };
00064   public:
00065     typedef value_type &reference;
00066     typedef const value_type &const_reference;
00067     typedef Rptr<T> pointer;
00068     typedef Rptr<const T> const_pointer;
00069     typedef typename std::vector<Node>::difference_type difference_type;
00070     typedef typename std::vector<Node>::size_type size_type;
00071   private:
00072     size_type begn;
00073     size_type rbegn;
00074     size_type sze;
00075     std::vector<Node> v;
00076   public:
00077     class const_iterator;
00078 
00080     class iterator {
00081       typename std::vector<Node>::iterator vi;
00082       friend class Rvec;
00083       friend class const_iterator;
00084       inline iterator(typename std::vector<Node>::iterator vi0):
00085         vi(vi0) {}
00086 
00087     public:
00088       typedef std::bidirectional_iterator_tag iterator_category;
00089       //typedef typename std::vector<Node>::iterator::iterator_category iterator_category;
00090       typedef Rvec::value_type value_type;
00091       typedef Rvec::difference_type difference_type;
00092 
00093       typedef Rvec::pointer pointer;
00094       typedef Rvec::reference reference;
00095 
00097       inline reference operator *() const { 
00098         return *vi->ptr; 
00099       }
00101       inline pointer operator ->() const { 
00102         return vi->ptr;
00103       }
00105       inline pointer ptr() const { 
00106         return vi->ptr; 
00107       }
00109       inline bool operator ==(const iterator &right) const { 
00110         return vi==right.vi; 
00111       }
00113       inline bool operator !=(const iterator &right) const { 
00114         return vi!=right.vi; 
00115       }
00117       inline bool operator <(const iterator &right) const { 
00118         return vi<right.vi; 
00119       }
00121       inline iterator & operator ++() {
00122         vi += vi->next;
00123         return *this; 
00124       }
00126       inline iterator operator ++(int) { 
00127         iterator tmp(*this);
00128         operator++(); 
00129         return tmp; 
00130       }
00132       inline iterator & operator --() {
00133         vi += vi->prev;
00134         return *this; 
00135       }
00137       inline iterator operator --(int) { 
00138         iterator tmp(*this);
00139         operator--(); 
00140         return tmp; 
00141       }
00142     };
00144     class const_iterator {
00145       typename std::vector<Node>::const_iterator vi;
00146       friend class Rvec;
00147       friend class iterator;
00148       inline const_iterator(typename std::vector<Node>::const_iterator vi0):
00149         vi(vi0) {}
00150 
00151     public:
00152       inline const_iterator(const iterator &src): vi(src.vi) {}
00153       typedef std::bidirectional_iterator_tag iterator_category;
00154       //typedef typename std::vector<Node>::const_iterator::iterator_category iterator_category;
00155       typedef Rvec::value_type value_type;
00156       typedef Rvec::difference_type difference_type;
00157 
00158       typedef Rvec::const_pointer pointer;
00159       typedef Rvec::const_reference reference;
00160 
00162       inline reference operator *() const { 
00163         return *vi->ptr; 
00164       }
00166       inline pointer operator ->() const { 
00167         return vi->ptr; 
00168       }
00170       inline pointer ptr() const { 
00171         return vi->ptr; 
00172       }
00174       inline bool operator ==(const const_iterator &right) const { 
00175         return vi==right.vi; 
00176       }
00178       inline bool operator !=(const const_iterator &right) const { 
00179         return vi!=right.vi; 
00180       }
00182       inline bool operator <(const const_iterator &right) const { 
00183         return vi<right.vi; 
00184       }
00186       inline const_iterator & operator ++() {
00187         vi += vi->next;
00188         return *this; 
00189       }
00191       inline const_iterator operator ++(int) { 
00192         const_iterator tmp(*this);
00193         operator++(); 
00194         return tmp; 
00195       }
00197       inline const_iterator & operator --() {
00198         vi += vi->prev;
00199         return *this; 
00200       }
00202       inline const_iterator operator --(int) { 
00203         const_iterator tmp(*this);
00204         operator--(); 
00205         return tmp; 
00206       }
00207     };
00209 
00210 
00211     inline Rvec(): begn(0), rbegn(0), sze(0), v(1) {
00212     }
00214 
00215 
00216 
00218     inline const_reference operator[](size_type n) const {
00219       if(!defined(n)) {
00220         throw std::out_of_range
00221           ("Rvec - attempt to access undefined element");
00222       }
00223       return *v[n+1].ptr;
00224     }
00227     inline const_pointer ptr(size_type n) const {
00228       if(!defined(n)) {
00229         throw std::out_of_range
00230           ("Rvec - attempt to access undefined element");
00231       }
00232       return v[n+1].ptr;
00233     }
00236     inline const_iterator begin() const { 
00237       return const_iterator(v.begin()+begn);
00238     }
00240     inline const_iterator end() const {
00241       return const_iterator(v.begin());
00242     }
00244     inline int ibegin() const {
00245       return begn-1;
00246     }
00248     inline int inext(int id) const {
00249       return id + v[id+1].next;
00250     }
00252     inline int iprev(int id) const {
00253       return id + v[id+1].prev;
00254     }
00256     inline size_type id(const iterator &it) const {
00257       return it.vi-v.begin()-1;
00258     }
00260     inline size_type id(const const_iterator &it) const {
00261       return it.vi-v.begin()-1;
00262     }
00264     inline size_type size() const {
00265       return sze;
00266     }
00268     inline bool defined(size_type n) const {
00269       return n+1>0 && n+1<v.size() && v[n+1].next!=0;
00270     }
00272     inline bool empty() const { 
00273       return begn==0;
00274     }
00276 
00277 
00278 
00280     inline iterator begin() { 
00281       return iterator(v.begin()+begn);
00282     }
00284     inline iterator end() { 
00285       return iterator(v.begin());
00286     }
00289     inline pointer ptr(size_type n) {
00290       if(!defined(n)) {
00291         throw std::out_of_range
00292           ("Rvec - attempt to access undefined position");
00293       }
00294       return v[n+1].ptr;
00295     }
00298     inline reference operator[](size_type n) {
00299       if(!defined(n)) {
00300         throw std::out_of_range
00301           ("Rvec - attempt to access undefined position");
00302       }
00303       return *v[n+1].ptr;
00304     }
00306     inline void swap(const Rvec &src) { 
00307       v.swap(src.v);
00308       size_type tmp = src.sze;
00309       src.sze = sze;
00310       sze = tmp;
00311       tmp = src.begn;
00312       src.begn = begn;
00313       begn = tmp;
00314     }
00317     inline size_type insert(pointer x) {
00318       size_type pos;
00319       for(pos=1; pos<v.size(); ++pos) {
00320         if(v[pos].next==0) {
00321           break;
00322         }
00323       }
00324       return set(pos-1,x);
00325     }
00333     size_type set(size_type pos, pointer x);
00335     inline void erase(size_type pos) {
00336       erase(iterator(v.begin()+pos+1));
00337     }
00339     void erase(const iterator &i);
00341     void clear() {
00342       v.resize(1);
00343       sze = rbegn = begn = 0;
00344     }
00346   };
00347 
00348   template<class T>
00349   typename Rvec<T>::size_type Rvec<T>::set(size_type pos, pointer x) {
00350     if(x==0) {
00351       if(defined(pos))
00352         erase(pos);
00353       return -1;
00354     }
00355     pos+=1;
00356     if(pos>=v.size()) {
00357       // Append element at end
00358       v.resize(pos+1);
00359     }
00360     if(v[pos].next==0) {
00361       size_type prev;
00362       // Find first preceeding non-null element
00363       for(prev=pos-1; prev>0; --prev) {
00364         if(v[prev].next!=0) {
00365           break;
00366         }
00367       }
00368       v[pos].prev=prev-pos;
00369       if(prev) {
00370         // We have a preceeding element!
00371         size_type next = prev+v[prev].next;
00372         v[pos].next=next-pos;
00373         v[prev].next=pos-prev;
00374         if(next) {
00375           // We have a following element!
00376           v[next].prev=pos-next;
00377         } else {
00378           // This element is the last
00379           rbegn = pos;
00380         }
00381       } else {
00382         // This element is the first
00383         begn = pos;
00384         size_type next;
00385         // Find first following non-null element
00386         for(next=pos+1; next<v.size(); ++next) {
00387           if(v[next].next!=0) {
00388             break;
00389           }
00390         }
00391         if(next<v.size()) {
00392           // We have a following element!
00393           v[pos].next = next-pos;
00394           v[next].prev = pos-next;
00395         } else {
00396           // This element is last
00397           v[pos].next = -pos;
00398           rbegn=pos;
00399         }
00400       }
00401       ++sze;
00402     }
00403     v[pos].ptr = x;
00404     return pos-1;
00405   }
00406 
00407   template<class T>
00408   void Rvec<T>::erase(const iterator &i) {
00409     size_type pos = id(i)+1;
00410     if(pos==0) {
00411       throw std::out_of_range
00412         ("Rvec - attempt to erase 'end()' iterator");
00413     }
00414     if(pos>v.size()) {
00415       throw std::out_of_range
00416         ("Rvec - attempt to erase element out of range");
00417     }
00418     if(v[pos].next==0) {
00419       throw std::out_of_range
00420         ("Rvec - attempt to erase undefined element");
00421     }
00422     size_type next = pos+v[pos].next;
00423     size_type prev = pos+v[pos].prev;
00424     --sze;
00425     if(next) {
00426       if(prev) {
00427         v[next].prev = prev-next;
00428         v[prev].next = next-prev;
00429       } else {
00430         // Element is at beginning
00431         v[next].prev = -next;
00432         begn = next;
00433       }
00434     } else {
00435       // Element is at end
00436       if(prev) {
00437         v[prev].next = -prev;
00438         rbegn = prev;
00439       } else {
00440         // Element was the only element
00441         rbegn = begn = 0;
00442       }
00443       v.resize(rbegn+1);
00444     }
00445     v[pos].ptr = 0;
00446     v[pos].next=v[pos].prev=0;
00447   }
00448 }
00449 #endif

Generated on Wed May 12 15:35:34 2004 for rptr by doxygen 1.3.3