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