00001 #ifndef CPPTL_VECTOR_H_INCLUDED
00002 # define CPPTL_VECTOR_H_INCLUDED
00003
00004 # include "_stlimpl.h"
00005
00006
00007
00008
00009
00010
00011 namespace CppTL {
00012
00013 template<class Item>
00014 class SmallMapBase
00015 {
00016 public:
00017 typedef unsigned int size_t;
00018
00019 SmallMapBase()
00020 : data_( 0 )
00021 , size_( 0 )
00022 , capacity_( 0 )
00023 {
00024 }
00025
00026 SmallMapBase( Item *data, size_t size, size_t capacity )
00027 : data_( data )
00028 , size_( size )
00029 , capacity_( capacity )
00030 {
00031 }
00032
00033 Item *data_;
00034 size_t size_;
00035 size_t capacity_;
00036 };
00037
00038
00039 template<class T>
00040 class SmallMapIteratorBase
00041 {
00042 public:
00043 typedef unsigned int size_t;
00044 typedef int difference_type;
00045 typedef SmallMapIteratorBase<T> SelfType;
00046 typedef T Item;
00047
00048 size_t index() const
00049 {
00050 CPPTL_ASSERT_MESSAGE( map_ != 0, "SmallMapIterator::index(): invalid iterator" );
00051 return current_ - map_->data_;
00052 }
00053
00054 bool operator ==( const SelfType &other ) const
00055 {
00056 return isEqual( other );
00057 }
00058
00059 bool operator !=( const SelfType &other ) const
00060 {
00061 return !isEqual( other );
00062 }
00063
00064 bool operator <( const SelfType &other ) const
00065 {
00066 return isLess( other );
00067 }
00068
00069 bool operator <=( const SelfType &other ) const
00070 {
00071 return !other.isLess( *this );
00072 }
00073
00074 bool operator >=( const SelfType &other ) const
00075 {
00076 return !isLess( other );
00077 }
00078
00079 bool operator >( const SelfType &other ) const
00080 {
00081 return other.isLess( *this );
00082 }
00083
00084 protected:
00085 SmallMapIteratorBase()
00086 : map_( 0 )
00087 , current_( 0 )
00088 {
00089 }
00090
00091 SmallMapIteratorBase( const SmallMapBase<Item> &map,
00092 Item *current )
00093 : map_( &map )
00094 , current_( current )
00095 {
00096 }
00097
00098
00099 T &deref() const
00100 {
00101 CPPTL_ASSERT_MESSAGE( current_ != 0,
00102 "SmallMapIterator: dereferencing invalid iterator" );
00103 return *current_;
00104 }
00105
00106 void increment()
00107 {
00108 CPPTL_ASSERT_MESSAGE( map_ && ( current_ < map_->data_ + map_->size_ ),
00109 "SmallMapIterator::increment: incrementing beyond end" );
00110 ++current_;
00111 }
00112
00113 void decrement()
00114 {
00115 CPPTL_ASSERT_MESSAGE( map_ && ( current_ > map_->data_ ),
00116 "SmallMapIterator::decrement: decrementing beyond beginning" );
00117 --current_;
00118 }
00119
00120 void advance( difference_type n )
00121 {
00122 if ( n != 0 )
00123 {
00124 CPPTL_ASSERT_MESSAGE( map_ && map_->size_ &&
00125 ( current_+n <= map_->data_ + map_->size_ && current_+n >= map_->data_),
00126 "SmallMapIterator::advance: advancing beyond end or beginning" );
00127 current_ += n;
00128 }
00129 }
00130
00131 difference_type computeDistance( const SelfType &other ) const
00132 {
00133 CPPTL_ASSERT_MESSAGE( map_->data_ == other.map_->data_, "Comparing iterator on different container." );
00134 return current_ - other.current_;
00135 }
00136
00137 bool isEqual( const SmallMapIteratorBase &other ) const
00138 {
00139 return current_ == other.current_;
00140 }
00141
00142 bool isLess( const SmallMapIteratorBase &other ) const
00143 {
00144 return current_ < other.current_;
00145 }
00146
00147 protected:
00148 const SmallMapBase<Item> *map_;
00149 Item *current_;
00150 };
00151
00152
00153
00154
00155 template<class T, class Traits>
00156 class SmallMapIterator : public SmallMapIteratorBase<T>
00157 {
00158 public:
00159 typedef unsigned int size_t;
00160 typedef int difference_type;
00161 typedef T value_type;
00162 typedef CPPTL_TYPENAME Traits::reference reference;
00163 typedef CPPTL_TYPENAME Traits::pointer pointer;
00164
00165 typedef SmallMapIterator<T,Traits> SelfType;
00166 typedef SmallMapIteratorBase<T> SuperClass;
00167 typedef SmallMapIterator< T, ::CppTL::Impl::NonConstIteratorTraits<T> > NonConstSmallMapIterator;
00168
00169 SmallMapIterator()
00170 {
00171 }
00172
00173
00174
00175 SmallMapIterator( const NonConstSmallMapIterator &other )
00176 : SuperClass( other )
00177 {
00178 }
00179
00180 SmallMapIterator( const SmallMapBase<T> &map, T *current )
00181 : SuperClass( map, current )
00182 {
00183 }
00184
00185 SmallMapIterator( const SmallMapBase<T> &map, size_t currentIndex )
00186 : SuperClass( map, map.data_ + currentIndex )
00187 {
00188 }
00189
00190 SelfType &operator++()
00191 {
00192 this->increment();
00193 return *this;
00194 }
00195
00196 SelfType operator++( int )
00197 {
00198 SelfType temp( *this );
00199 ++*this;
00200 return temp;
00201 }
00202
00203 SelfType &operator--()
00204 {
00205 this->decrement();
00206 return *this;
00207 }
00208
00209 SelfType operator--( int )
00210 {
00211 SelfType temp( *this );
00212 --*this;
00213 return temp;
00214 }
00215
00216 SelfType &operator +=( difference_type n )
00217 {
00218 this->advance( n );
00219 return *this;
00220 }
00221
00222 SelfType operator +( difference_type n ) const
00223 {
00224 SelfType temp( *this );
00225 return temp += n;
00226 }
00227
00228 SelfType &operator -=( difference_type n )
00229 {
00230 this->advance( -n );
00231 return *this;
00232 }
00233
00234 SelfType operator -( difference_type n ) const
00235 {
00236 SelfType temp( *this );
00237 return temp -= n;
00238 }
00239
00240 reference operator[]( difference_type n ) const
00241 {
00242 return *( *this + n );
00243 }
00244
00245 reference operator *() const
00246 {
00247 return this->deref();
00248 }
00249
00250 pointer operator->() const
00251 {
00252 return &(this->deref());
00253 }
00254
00255 difference_type operator -( const SelfType &other ) const
00256 {
00257 return computeDistance( other );
00258 }
00259 };
00260
00261
00262
00264 template< class Key
00265 , class Value
00266 , class PredLess = CppTL::LessPred<Key>
00267 , class Allocator = CppTL::MallocAllocator< Pair<Key,Value> > >
00268 class SmallMap : private SmallMapBase< Pair<Key,Value> >
00269 {
00270 public:
00271 typedef Pair<Key,Value> Item;
00272
00273 typedef Item value_type;
00274 typedef Key key_type;
00275 typedef Value mapped_type;
00276 typedef SmallMapIterator<Item, ::CppTL::Impl::NonConstIteratorTraits<Item> > iterator;
00277 typedef SmallMapIterator<Item, ::CppTL::Impl::ConstIteratorTraits<Item> > const_iterator;
00278 typedef SmallMap<Key, Value, PredLess, Allocator> SelfType;
00279 typedef SmallMapBase< Pair<Key,Value> > SuperClass;
00280
00281 SmallMap()
00282 {
00283 }
00284
00285 SmallMap( const SmallMap &other )
00286 : SuperClass( 0, other.size_, other.size_ )
00287 , allocator_( other.allocator_ )
00288 {
00289 this->data_ = allocator_.allocateArray( this->size_ );
00290 CPPTL_TRY_BEGIN
00291 {
00292 ::CppTL::Impl::copy_with_construct( other.begin(), other.end(), this->data_ );
00293 }
00294 CPPTL_TRY_END_CLEANUP( allocator.releaseArray( this->data_, this->size_ ) )
00295 }
00296
00297 ~SmallMap()
00298 {
00299 }
00300
00301 SelfType &operator =( const SmallMap &other )
00302 {
00303 SelfType temp( other );
00304 swap( temp );
00305 return *this;
00306 }
00307
00308 size_t size() const
00309 {
00310 return this->size_;
00311 }
00312
00313 const_iterator find( const Key &key ) const
00314 {
00315 Item *found = lookUp( key );
00316 if ( found )
00317 return const_iterator( *this, found );
00318 return end();
00319 }
00320
00321 iterator find( const Key &key )
00322 {
00323 Item *found = lookUp( key );
00324 if ( found )
00325 return iterator( *this, found );
00326 return end();
00327 }
00328
00329 iterator lower_bound( const Key &key )
00330 {
00331 size_t index = insertionIndex( key, 0 );
00332 return iterator( *this, index );
00333 }
00334
00335 iterator upper_bound( const Key &key )
00336 {
00337 size_t index = insertionIndex( key, 0 );
00338 return iterator( *this, index );
00339 }
00340
00341 Pair<iterator,iterator> equal_range( const Key &key )
00342 {
00343 size_t index = insertionIndex( key, 0 );
00344 iterator it( *this, index );
00345 return Pair<iterator,iterator>( it, it );
00346 }
00347
00348 const_iterator lower_bound( const Key &key ) const
00349 {
00350 size_t index = insertionIndex( key, 0 );
00351 return const_iterator( *this, index );
00352 }
00353
00354 const_iterator upper_bound( const Key &key ) const
00355 {
00356 size_t index = insertionIndex( key, 0 );
00357 return const_iterator( *this, index );
00358 }
00359
00360 Pair<const_iterator,const_iterator> equal_range( const Key &key ) const
00361 {
00362 size_t index = insertionIndex( key, 0 );
00363 const_iterator it( *this, index );
00364 return Pair<const_iterator,const_iterator>( it, it );
00365 }
00366
00367 void clear()
00368 {
00369 SelfType temp;
00370 swap( temp );
00371 }
00372
00373 iterator begin()
00374 {
00375 return iterator( *this, this->data_ );
00376 }
00377
00378 iterator end()
00379 {
00380 return iterator( *this, this->size_ );
00381 }
00382
00383 const_iterator begin() const
00384 {
00385 return const_iterator( *this, this->data_ );
00386 }
00387
00388 const_iterator end() const
00389 {
00390 return const_iterator( *this, this->size_ );
00391 }
00392
00393 size_t count( const Key &key ) const
00394 {
00395 return lookUp( key ) ? 1 : 0;
00396 }
00397
00398 bool empty() const
00399 {
00400 return this->size_ == 0;
00401 }
00402
00403
00404
00405 iterator erase( iterator where )
00406 {
00407 CPPTL_ASSERT_MESSAGE( where >= begin() && where < end(), "SmallMap<T>::erase(): invalid iterator" );
00408 ::CppTL::Impl::copy_and_destroy( where+1, end(), where );
00409 --(this->size_);
00410 return where;
00411 }
00412
00413 iterator erase( iterator first, iterator last )
00414 {
00415 size_t whereIndex = first.index();
00416 size_t count = last - first;
00417 ::CppTL::Impl::copy_and_destroy( last, end(), first );
00418 this->size_ -= count;
00419 return iterator( *this, whereIndex );
00420 }
00421
00422 iterator erase( const Key &key )
00423 {
00424 Item *found = lookUp( key );
00425 if ( found )
00426 return erase( iterator( *this, found ) );
00427 return end();
00428 }
00429
00430 Value &operator[]( const Key &key )
00431 {
00432 typedef Pair<iterator,bool> ResultType;
00433 size_t whereIndex = insertionIndex( key, 0 );
00434 if ( whereIndex < this->size_
00435 && !less_( key, this->data_[whereIndex].first ) )
00436 {
00437 return this->data_[whereIndex].second;
00438 }
00439 return doInsert( whereIndex, Item( key, Value() ) )->second;
00440 }
00441
00442 Pair<iterator,bool> insert( const Item &item )
00443 {
00444 typedef Pair<iterator,bool> ResultType;
00445 size_t whereIndex = insertionIndex( item.first, 0 );
00446 if ( whereIndex < this->size_
00447 && !less_( item.first, this->data_[whereIndex].first ) )
00448 {
00449 return ResultType( iterator( *this, whereIndex ), false );
00450 }
00451 return ResultType( doInsert( whereIndex, item ), true );
00452 }
00453
00454 iterator insert( iterator where, const Item &item )
00455 {
00456 size_t whereIndex = insertionIndex( item.first, where.index() );
00457 if ( this->size_ == this->capacity_ )
00458 {
00459 if ( reserve( 1, whereIndex, &item ) )
00460 return iterator( *this, whereIndex );
00461 }
00462 ++(this->size_);
00463 iterator itWhere( *this, whereIndex );
00464 ::CppTL::Impl::copy_backwards_and_destroy( itWhere, end()-1, end() );
00465 ::CppTL::Impl::construct( *itWhere, item );
00466 return itWhere;
00467 }
00468
00469 void insert( const_iterator first , const_iterator last )
00470 {
00471 reserve( last - first );
00472 iterator itHint = begin();
00473 for ( ; first != last; ++first )
00474 itHint = insert( itHint, *first ).first;
00475 }
00476
00477 void swap( SelfType &other )
00478 {
00479 CppTL::swap( this->data_, other.data_ );
00480 CppTL::swap( this->size_, other.size_ );
00481 CppTL::swap( this->capacity_, other.capacity_ );
00482 allocator_.swap( other.allocator_ );
00483 CppTL::swap( less_, other.less_ );
00484 }
00485
00486 bool operator <( const SelfType &other ) const
00487 {
00488 if ( this->size_ < other.size_ )
00489 return true;
00490 if ( this->size_ > other.size_ || this->size_ == 0 )
00491 return false;
00492 Item *i1 = this->data_, *i2 = other.data_;
00493 Item *i1end = this->data_ + this->size_;
00494 for ( ; i1 != i1end; ++i1, ++i2 )
00495 {
00496 if ( itemIsLess( *i1, *i2 ) )
00497 return true;
00498 if ( itemIsLess( *i2, *i1 ) )
00499 return false;
00500 }
00501 return false;
00502 }
00503
00504 bool operator ==( const SelfType &other ) const
00505 {
00506 if ( this->size_ != other.size_ )
00507 return false;
00508 Item *i1 = this->data_, *i2 = other.data_;
00509 Item *i1end = this->data_ + this->size_;
00510 for ( ; i1 != i1end; ++i1, ++i2 )
00511 {
00512 if ( itemIsLess( *i1, *i2 ) || itemIsLess( *i2, *i1 ) )
00513 return false;
00514 }
00515 return true;
00516 }
00517
00518 private:
00519
00520
00521 bool reserve( size_t count, size_t insertIndex = 0, const Item *item = 0)
00522 {
00523 if ( this->size_ + count <= this->capacity_ )
00524 return false;
00525 const size_t initialCapacity = 8;
00526 const size_t minCapacityIncrement = 8;
00527 size_t newCapacity = this->size_ + count;
00528 newCapacity += CPPTL_MAX( newCapacity / 4, minCapacityIncrement );
00529 newCapacity = CPPTL_MAX( initialCapacity, newCapacity );
00530 Item *newData = allocator_.allocateArray( newCapacity );
00531 CPPTL_TRY_BEGIN
00532 {
00533 if ( !item )
00534 insertIndex = this->size_;
00535 ::CppTL::Impl::copy_and_destroy( begin(), begin() + insertIndex, newData );
00536 if ( item )
00537 {
00538 new (newData+insertIndex) Item( *item );
00539 ::CppTL::Impl::copy_and_destroy( begin() + insertIndex, end(),
00540 newData + (insertIndex+1) );
00541 }
00542 }
00543 CPPTL_TRY_END_CLEANUP( allocator_.release( newData, newCapacity ) );
00544 if ( this->data_ )
00545 allocator_.releaseArray( this->data_, this->capacity_ );
00546 this->data_ = newData;
00547 this->capacity_ = newCapacity;
00548 if ( item )
00549 ++(this->size_);
00550 return true;
00551 }
00552
00553 size_t insertionIndex( const Key &key, size_t min = 0 ) const
00554 {
00555 size_t max = this->size_;
00556 while ( min != max )
00557 {
00558 size_t mid = (max+min) / 2;
00559 if ( less_( this->data_[mid].first, key ) )
00560 min = mid + 1;
00561 else
00562 max = mid;
00563 }
00564 return min;
00565 }
00566
00567 Item *lookUp( const Key &key ) const
00568 {
00569 size_t pos = insertionIndex( key, 0 );
00570 if ( pos < this->size_ && !less_( key, this->data_[pos].first ) )
00571 return this->data_ + pos;
00572 return 0;
00573 }
00574
00575 iterator doInsert( size_t whereIndex, const Item &item )
00576 {
00577 if ( this->size_ == this->capacity_ )
00578 {
00579 if ( reserve( 1, whereIndex, &item ) )
00580 return begin() + whereIndex;
00581 }
00582 ++(this->size_);
00583 iterator itWhere( *this, whereIndex );
00584 iterator itEnd = end();
00585 if ( whereIndex != this->size_ - 1 )
00586 ::CppTL::Impl::copy_backwards_and_destroy( itWhere, itEnd-1, itEnd );
00587 ::CppTL::Impl::construct( *itWhere, item);
00588 return itWhere;
00589 }
00590
00591 bool itemIsLess( const Item &a, const Item &b ) const
00592 {
00593 return less_( a.first, b.first ) ||
00594 ( !less_(b.first, a.first) && a.second < b.second );
00595 }
00596
00597
00598 private:
00599 Allocator allocator_;
00600 PredLess less_;
00601 };
00602
00603
00604
00605 }
00606
00607
00608 #endif // CPPTL_VECTOR_H_INCLUDED