BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/vector.h
Go to the documentation of this file.
00001 // Copyright (c) 1997, 1998, 1999, 2000  Utrecht University (The Netherlands),
00002 // ETH Zurich (Switzerland), Freie Universitaet Berlin (Germany),
00003 // INRIA Sophia-Antipolis (France), Martin-Luther-University Halle-Wittenberg
00004 // (Germany), Max-Planck-Institute Saarbruecken (Germany), RISC Linz (Austria),
00005 // and Tel-Aviv University (Israel).  All rights reserved.
00006 //
00007 // This file is part of CGAL (www.cgal.org); you can redistribute it and/or
00008 // modify it under the terms of the GNU Lesser General Public License as
00009 // published by the Free Software Foundation; version 2.1 of the License.
00010 // See the file LICENSE.LGPL distributed with CGAL.
00011 //
00012 // Licensees holding a valid commercial license may use this file in
00013 // accordance with the commercial license agreement provided with the software.
00014 //
00015 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00016 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00017 //
00018 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/STL_Extension/include/CGAL/vector.h $
00019 // $Id: vector.h 41698 2008-01-20 15:27:47Z spion $
00020 // 
00021 //
00022 // Author(s)     : Andreas Fabri <Andreas.Fabri@sophia.inria.fr>
00023 //                 Lutz Kettner <kettner@mpi-sb.mpg.de>
00024 
00025 #ifndef CGAL_VECTOR_H
00026 #define CGAL_VECTOR_H 1
00027 
00028 #include <CGAL/basic.h>
00029 #include <CGAL/memory.h>
00030 #include <iterator>
00031 #include <algorithm>
00032 #include <memory>
00033 #include <cstddef>
00034 
00035 CGAL_BEGIN_NAMESPACE
00036 
00037 namespace CGALi {
00038 
00039 // We give the vector container class a class based iterator implementation.
00040 // It ensures that iterator_traits work on compilers not supporting
00041 // partial specializations and it guarantees that default initialization
00042 // initializes the internal pointer to 0. Allows explicit construction 
00043 // from a pointer.
00044 
00045 template < class T, class Ref, class Ptr>
00046 class vector_iterator {
00047 private:
00048     Ptr ptr;
00049 public:
00050     typedef vector_iterator< T, Ref, Ptr>      Self;
00051     typedef T                                  value_type;
00052     typedef Ref                                reference;
00053     typedef Ptr                                pointer;
00054     typedef std::ptrdiff_t                     difference_type;
00055     typedef std::random_access_iterator_tag    iterator_category;
00056 
00057     // CREATION
00058     // --------
00059     vector_iterator() : ptr(0) {}                // explicitly set to 0
00060     explicit vector_iterator( Ptr p) : ptr(p) {} // construction from pointer
00061 
00062     // Allows construction of const_iterator from iterator
00063     template < class A, class B, class C>
00064     vector_iterator( const vector_iterator<A,B,C>& i) : ptr( &*i) {}
00065 
00066     // OPERATIONS Forward Category
00067     // ---------------------------
00068 
00069     bool      operator==( const Self& i) const { return ( ptr == i.ptr); }
00070     bool      operator!=( const Self& i) const { return !(*this == i); }
00071     reference operator*()                const { return *ptr; }
00072     pointer   operator->()               const { return ptr; }
00073     Self& operator++() {
00074         ++ptr;
00075         return *this;
00076     }
00077     Self  operator++(int) {
00078         Self tmp = *this;
00079         ++*this;
00080         return tmp;
00081     }
00082 
00083     // OPERATIONS Bidirectional Category
00084     // ---------------------------------
00085     Self& operator--() {
00086         --ptr;
00087         return *this;
00088     }
00089     Self  operator--(int) {
00090         Self tmp = *this;
00091         --*this;
00092         return tmp;
00093     }
00094 
00095     // OPERATIONS Random Access Category
00096     // ---------------------------------
00097     Self& operator+=( difference_type n) {
00098         ptr += n;
00099         return *this;
00100     }
00101     Self  operator+( difference_type n) const {
00102         Self tmp = *this;
00103         return tmp += n;
00104     }
00105     Self& operator-=( difference_type n) { return operator+=( -n); }
00106     Self  operator-( difference_type n) const {
00107         Self tmp = *this;
00108         return tmp += -n;
00109     }
00110     difference_type  operator-( const Self& i) const { return ptr - i.ptr; }
00111     reference  operator[]( difference_type n) const {
00112         Self tmp = *this;
00113         tmp += n;
00114         return tmp.operator*();
00115     }
00116     bool operator< ( const Self& i) const { return ( ptr < i.ptr); }
00117     bool operator> ( const Self& i) const { return i < *this;    }
00118     bool operator<=( const Self& i) const { return !(i < *this); }
00119     bool operator>=( const Self& i) const { return !(*this < i); }
00120 };
00121 
00122 template < class T, class Ref, class Ptr> inline
00123 vector_iterator<T,Ref,Ptr> 
00124 operator+( std::ptrdiff_t n, vector_iterator<T,Ref,Ptr> i) {
00125     return i += n;
00126 }
00127 
00128 
00129 template < class T, class Alloc = CGAL_ALLOCATOR(T)>
00130 class vector {
00131 public:
00132     typedef Alloc           Allocator;
00133     typedef Alloc           allocator_type; // STL compliant
00134 
00135     // Note: the standard requires the following types to be equivalent
00136     // to T, T*, const T*, T&, const T&, size_t, and ptrdiff_t, respectively.
00137     // So we don't pass these types to the iterators explicitly.
00138     typedef typename Allocator::value_type           value_type;
00139     typedef typename Allocator::pointer              pointer;
00140     typedef typename Allocator::const_pointer        const_pointer;
00141     typedef typename Allocator::reference            reference;
00142     typedef typename Allocator::const_reference      const_reference;
00143     typedef typename Allocator::size_type            size_type;
00144     typedef typename Allocator::difference_type      difference_type;
00145     typedef std::random_access_iterator_tag          iterator_category;
00146     typedef vector_iterator< T, reference, pointer>  iterator;
00147     typedef vector_iterator< T, const_reference, const_pointer>
00148                                                      const_iterator;
00149     typedef vector< T, Alloc>                        Self;
00150 
00151     typedef std::reverse_iterator<iterator>          reverse_iterator;
00152     typedef std::reverse_iterator<const_iterator>    const_reverse_iterator;
00153 
00154 protected:
00155 #ifndef _MSC_VER
00156     // Somehow the static initialization does not work correctly for MSVC
00157     // ---> strange linker errors
00158     static
00159 #endif // _MSC_VER
00160     Allocator alloc;
00161 
00162     iterator start_;
00163     iterator finish;
00164     iterator end_of_storage;
00165 
00166     // ALLOCATION AND CONSTRUCTION HELPERS
00167     void construct( iterator i, const T& x) { alloc.construct( &*i, x);}
00168     void destroy( iterator i) { alloc.destroy( &*i); }
00169     void destroy( iterator first, iterator last) {
00170         // destroy in reverse order than construction
00171         while ( last != first) {
00172             --last;
00173             destroy( last);
00174         }
00175     }
00176     void deallocate() {
00177         if ( &*start_)
00178             alloc.deallocate( &*start_, end_of_storage - start_ );
00179     }
00180 
00181 protected:
00182     // pointer versions of begin()/end() to call the various
00183     // standard algorithms with the (possibly) more efficient pointers.
00184     pointer         pbegin()         { return &*start_; }
00185     const_pointer   pbegin()   const { return &*start_; }
00186     pointer         pend()           { return &*finish; }
00187     const_pointer   pend()     const { return &*finish; }
00188 
00189 public:
00190     // ACCESS
00191     // ------
00192     iterator        begin()          { return start_; }
00193     const_iterator  begin()    const { return start_; }
00194     iterator        end()            { return finish; }
00195     const_iterator  end()      const { return finish; }
00196     size_type       size()     const { return size_type(end() - begin()); }
00197     size_type       max_size() const { return size_type(-1) / sizeof(T); }
00198     size_type       capacity() const {
00199                         return size_type(end_of_storage - start_);
00200     }
00201     bool            empty()    const { return begin() == end(); }
00202 
00203     reference       front()          { return *begin(); }
00204     const_reference front()    const { return *begin(); }
00205     reference       back()           { return *(end() - 1); }
00206     const_reference back()     const { return *(end() - 1); }
00207     reference       operator[] ( size_type n)       { return *(begin() + n); }
00208     const_reference operator[] ( size_type n) const { return *(begin() + n); }
00209     reference       at( size_type n)                { return *(begin() + n); }
00210     const_reference at( size_type n)          const { return *(begin() + n); }
00211 
00212     Allocator       get_allocator() const { return alloc; }
00213 
00214     reverse_iterator       rbegin() { return reverse_iterator(end()); }
00215     const_reverse_iterator rbegin() const {
00216         return const_reverse_iterator(end());
00217     }
00218     reverse_iterator       rend() { return reverse_iterator(begin()); }
00219     const_reverse_iterator rend() const {
00220         return const_reverse_iterator(begin());
00221     }
00222 
00223 
00224     // COMPARISON
00225     // ----------
00226     bool      operator==( const Self& y) const {
00227         return size() == y.size() && std::equal( pbegin(), pend(), y.pbegin());
00228     }
00229     bool      operator!=( const Self& y) const { return !(*this == y); }
00230     bool operator< ( const Self& y) const {
00231         return std::lexicographical_compare( pbegin(),   pend(),
00232                                              y.pbegin(), y.pend());
00233     }
00234     bool operator> ( const Self& y) const { return y < *this;    }
00235     bool operator<=( const Self& y) const { return !(y < *this); }
00236     bool operator>=( const Self& y) const { return !(*this < y); }
00237 
00238     // CREATION
00239     // --------
00240     explicit vector()
00241         : start_(0), finish(0), end_of_storage(0) {}
00242     explicit vector( const Alloc& a)
00243         : start_(0), finish(0), end_of_storage(0) { alloc = a; }
00244     explicit vector( size_type n, const T& val) { fill_initialize(n, val); }
00245     explicit vector( size_type n) { fill_initialize(n, T()); }
00246 
00247     vector( const Self& x) {
00248         start_ = allocate_and_copy( x.end() - x.begin(), x.begin(), x.end());
00249         finish = start_ + (x.end() - x.begin());
00250         end_of_storage = finish;
00251     }
00252 
00253     template <class InputIterator>
00254     vector( InputIterator first, InputIterator last, const Alloc& a = Alloc())
00255         : start_(0), finish(0), end_of_storage(0)
00256     {
00257         alloc = a;
00258         typedef std::iterator_traits<InputIterator> Traits;
00259         typedef typename Traits::iterator_category  iterator_category;
00260         range_initialize( first, last, iterator_category());
00261     }
00262 
00263     ~vector() { 
00264         destroy( start_, finish);
00265         deallocate();
00266     }
00267 
00268     vector<T, Alloc>& operator=(const Self& x) {
00269         if (&x != this) {
00270             if ( x.size() > capacity()) {
00271                 iterator tmp = allocate_and_copy( x.end() - x.begin(),
00272                                                   x.begin(),
00273                                                   x.end());
00274                 destroy( start_, finish);
00275                 deallocate();
00276                 start_ = tmp;
00277                 end_of_storage = start_ + (x.end() - x.begin());
00278             } else if (size() >= x.size()) {
00279                 iterator i = std::copy( x.begin(), x.end(), begin());
00280                 destroy( i, finish);
00281             } else {
00282                 std::copy( x.begin(), x.begin() + size(), begin());
00283                 std::uninitialized_copy(x.pbegin() + size(), x.pend(), pend());
00284             }
00285             finish = start_ + x.size();
00286         }
00287         return *this;
00288     }
00289 
00290     void swap( Self& x) {
00291         std::swap( start_, x.start_);
00292         std::swap( finish, x.finish);
00293         std::swap( end_of_storage, x.end_of_storage);
00294     }
00295 
00296     void reserve( size_type n) {
00297         if ( capacity() < n) {
00298             const size_type old_size = size();
00299             iterator tmp = allocate_and_copy( n, start_, finish);
00300             destroy(start_, finish);
00301             deallocate();
00302             start_ = tmp;
00303             finish = tmp + old_size;
00304             end_of_storage = start_ + n;
00305         }
00306     }
00307 
00308     // INSERTION
00309     // ---------
00310     void push_back( const T& x) {
00311         if ( finish != end_of_storage) {
00312             construct( finish, x);
00313             ++finish;
00314         } else {
00315             insert_aux( end(), x);
00316         }
00317     }
00318 
00319     iterator insert( iterator position, const T& x) {
00320         size_type n = position - begin();
00321         if (finish != end_of_storage && position == end()) {
00322             construct( finish, x);
00323             ++finish;
00324         } else {
00325             insert_aux( position, x);
00326         }
00327         return begin() + n;
00328     }
00329     iterator insert(iterator position) { return insert( position, T()); }
00330 
00331     template <class InputIterator>
00332     void insert( iterator position, InputIterator first, InputIterator last) {
00333         typedef std::iterator_traits<InputIterator> Traits;
00334         typedef typename Traits::iterator_category  iterator_category;
00335         range_insert( position, first, last, iterator_category());
00336     }
00337     void insert( iterator pos, size_type n, const T& x);
00338 
00339     // REMOVAL
00340     // -------
00341     void pop_back() {
00342         --finish;
00343         destroy( finish);
00344     }
00345     iterator erase( iterator position) {
00346         if (position + 1 != end())
00347             std::copy( position + 1, finish, position);
00348         --finish;
00349         destroy(finish);
00350         return position;
00351     }
00352     iterator erase( iterator first, iterator last) {
00353         iterator i = std::copy( last, finish, first);
00354         destroy( i, finish);
00355         finish = finish - (last - first);
00356         return first;
00357     }
00358     void clear() { erase( begin(), end()); }
00359 
00360     // ASSIGNMENT
00361     // ----------
00362     template <class InputIterator>
00363     void assign( InputIterator first, InputIterator last) {
00364         clear();
00365         insert( begin(), first, last);
00366     }
00367     void assign( size_type n, const T& u) {
00368         clear();
00369         insert( begin(), n, u);
00370     }
00371 
00372     void resize( size_type new_size, const T& x) {
00373         if (new_size < size()) 
00374             erase( begin() + new_size, end());
00375         else
00376             insert( end(), new_size - size(), x);
00377     }
00378     void resize( size_type new_size) { resize( new_size, T()); }
00379 
00380 protected:
00381     // INTERNAL
00382     // --------
00383     void insert_aux( iterator position, const T& x);
00384 
00385     void fill_initialize( size_type n, const T& value) {
00386         start_ = allocate_and_fill(n, value);
00387         finish = start_ + n;
00388         end_of_storage = finish;
00389     }
00390 
00391     iterator allocate_and_fill( size_type n, const T& x) {
00392         iterator result = iterator( alloc.allocate(n));
00393         try {
00394             std::uninitialized_fill_n( &*result, n, x);
00395             return result;
00396         }
00397         catch(...) { 
00398             alloc.deallocate( &*result, n);
00399             throw;
00400         }
00401     }
00402 
00403     template <class ForwardIterator>
00404     iterator allocate_and_copy( size_type n,
00405                                 ForwardIterator first,
00406                                 ForwardIterator last) {
00407         iterator result = iterator( alloc.allocate(n));
00408         try {
00409             std::uninitialized_copy( first, last, &*result);
00410             return result;
00411         }
00412         catch(...) { 
00413             alloc.deallocate( &*result, n);
00414             throw;
00415         }
00416     }
00417 
00418     template <class InputIterator>
00419     void range_initialize(InputIterator first,
00420                           InputIterator last,
00421                           std::input_iterator_tag) {
00422         for ( ; first != last; ++first)
00423             push_back(*first);
00424     }
00425 
00426     // This function is only called by the constructor.  We have to worry
00427     //  about resource leaks, but not about maintaining invariants.
00428     template <class ForwardIterator>
00429     void range_initialize( ForwardIterator first,
00430                            ForwardIterator last,
00431                            std::forward_iterator_tag) {
00432         size_type n = std::distance( first, last);
00433         start_ = allocate_and_copy( n, first, last);
00434         finish = start_ + n;
00435         end_of_storage = finish;
00436     }
00437 
00438     template <class InputIterator>
00439     void range_insert( iterator pos,
00440                        InputIterator first,
00441                        InputIterator last,
00442                        std::input_iterator_tag) {
00443         for ( ; first != last; ++first) {
00444             pos = insert( pos, *first);
00445             ++pos;
00446         }
00447     }
00448 
00449     template <class ForwardIterator>
00450     void range_insert( iterator position,
00451                        ForwardIterator first,
00452                        ForwardIterator last,
00453                        std::forward_iterator_tag) {
00454         if (first != last) {
00455             size_type n = std::distance(first, last);
00456             if ( size_type(end_of_storage - finish) >= n) {
00457                 const size_type elems_after = finish - position;
00458                 iterator old_finish = finish;
00459                 if (elems_after > n) {
00460                     std::uninitialized_copy( pend() - n, pend(), pend());
00461                     finish += n;
00462                     std::copy_backward( position, old_finish - n, old_finish);
00463                     std::copy( first, last, position);
00464                 } else {
00465                     ForwardIterator mid = first;
00466                     std::advance( mid, elems_after);
00467                     std::uninitialized_copy( mid, last, pend());
00468                     finish += n - elems_after;
00469                     std::uninitialized_copy( position, old_finish, pend());
00470                     finish += elems_after;
00471                     std::copy( first, mid, position);
00472                 }
00473             } else {
00474                 const size_type old_size = size();
00475                 const size_type len = old_size + (std::max)( old_size, n);
00476                 iterator new_start = iterator( alloc.allocate(len));
00477                 iterator new_finish = new_start;
00478                 try {
00479                     new_finish = iterator( 
00480                         std::uninitialized_copy(start_, position,&*new_start));
00481                     new_finish = iterator(
00482                         std::uninitialized_copy( first, last, &*new_finish));
00483                     new_finish = iterator( 
00484                         std::uninitialized_copy(position,finish,&*new_finish));
00485                 }
00486                 catch(...) {
00487                     destroy( new_start, new_finish);
00488                     alloc.deallocate( &*new_start, len);
00489                     throw;
00490                 }
00491                 destroy( start_, finish);
00492                 deallocate();
00493                 start_ = new_start;
00494                 finish = new_finish;
00495                 end_of_storage = new_start + len;
00496             }
00497         }
00498     }
00499 }; // class vector
00500 
00501 #ifndef _MSC_VER
00502 // init static member allocator object
00503 template <class T, class Alloc>
00504 Alloc vector< T, Alloc>::alloc = Alloc();
00505 #endif // _MSC_VER
00506 
00507 
00508 template <class T, class Alloc>
00509 inline void swap( vector<T, Alloc>& x, vector<T, Alloc>& y) {
00510     x.swap(y);
00511 }
00512 
00513 template <class T, class Alloc>
00514 void vector<T, Alloc>::insert_aux( iterator position, const T& x) {
00515     if ( finish != end_of_storage) {
00516         construct( finish, *(finish - 1));
00517         ++finish;
00518         T x_copy = x;
00519         std::copy_backward( position, finish - 2, finish - 1);
00520         *position = x_copy;
00521     } else {
00522         const size_type old_size = size();
00523         const size_type len = old_size != 0 ? 2 * old_size : 1;
00524         iterator new_start = iterator( alloc.allocate(len));
00525         iterator new_finish = new_start;
00526         try {
00527             new_finish = iterator(
00528                 std::uninitialized_copy(start_, position, &*new_start));
00529             construct( new_finish, x);
00530             ++new_finish;
00531             new_finish = iterator(
00532                 std::uninitialized_copy(position,finish,&*new_finish));
00533         }
00534         catch(...) {
00535             destroy( new_start, new_finish); 
00536             alloc.deallocate( &*new_start, len);
00537             throw;
00538         }
00539         destroy( begin(), end());
00540         deallocate();
00541         start_ = new_start;
00542         finish = new_finish;
00543         end_of_storage = new_start + len;
00544     }
00545 }
00546 
00547 
00548 template <class T, class Alloc>
00549 void vector<T, Alloc>::insert( iterator position, size_type n, const T& x) {
00550     if (n != 0) {
00551         if ( size_type(end_of_storage - finish) >= n) {
00552             T x_copy = x;
00553             const size_type elems_after = finish - position;
00554             iterator old_finish = finish;
00555             if (elems_after > n) {
00556                 std::uninitialized_copy( pend() - n, pend(), pend());
00557                 finish += n;
00558                 std::copy_backward( position, old_finish - n, old_finish);
00559                 std::fill( position, position + n, x_copy);
00560             } else {
00561                 std::uninitialized_fill_n( pend(), n - elems_after, x_copy);
00562                 finish += n - elems_after;
00563                 std::uninitialized_copy( position, old_finish, pend());
00564                 finish += elems_after;
00565                 std::fill(position, old_finish, x_copy);
00566             }
00567         } else {
00568             const size_type old_size = size();        
00569             const size_type len = old_size + (std::max)(old_size, n);
00570             iterator new_start = iterator( alloc.allocate(len));
00571             iterator new_finish = new_start;
00572             try {
00573                 new_finish = iterator(
00574                     std::uninitialized_copy( start_, position, &*new_start));
00575                 std::uninitialized_fill_n( &*new_finish, n, x);
00576                 new_finish += n;
00577                 new_finish = iterator( 
00578                     std::uninitialized_copy( position, finish, &*new_finish));
00579             }
00580             catch(...) {
00581                 destroy( new_start, new_finish);
00582                 alloc.deallocate( &*new_start, len);
00583                 throw;
00584             }
00585             destroy( start_, finish);
00586             deallocate();
00587             start_ = new_start;
00588             finish = new_finish;
00589             end_of_storage = new_start + len;
00590         }
00591     }
00592 }
00593 
00594 } // namespace CGALi
00595 
00596 CGAL_END_NAMESPACE
00597 
00598 #endif // CGAL_VECTOR_H //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines