Skip to content
Snippets Groups Projects
Commit 1234b051 authored by Martin Nolte's avatar Martin Nolte
Browse files

make StaticArray flexible and rename to DynamicArray

[[Imported from SVN: r6888]]
parent 1827da4b
No related branches found
No related tags found
No related merge requests found
containerincludedir = $(includedir)/dune/common/container
containerinclude_HEADERS = array.hh arraylist.hh bitsetvector.hh sllist.hh staticarray.hh
containerinclude_HEADERS = array.hh arraylist.hh bitsetvector.hh dynamicarray.hh sllist.hh
SUBDIRS = test
......
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifndef DUNE_DYNAMICARRAY_HH
#define DUNE_DYNAMICARRAY_HH
#include <cassert>
#include <memory>
#include <dune/common/exceptions.hh>
#include <dune/common/nullptr.hh>
namespace Dune
{
// CapacityManager
// ---------------
template< class sz_t = std::size_t >
class CapacityManager
{
typedef CapacityManager< sz_t > This;
public:
typedef sz_t size_type;
template< class _sz_t >
struct rebind { typedef CapacityManager< _sz_t > other; };
CapacityManager () : capacity_( 0 ) {}
template< class _sz_t >
CapacityManager ( const CapacityManager< _sz_t > & ) : capacity_( 0 ) {}
CapacityManager ( const This & ) : capacity_( 0 ) {}
template< class _sz_t >
const This &operator= ( const CapacityManager< _sz_t > & ) { return *this; }
const This &operator= ( const This & ) { return *this; }
size_type capacity ( size_type current_size ) const { return capacity_; }
std::pair< size_type, size_type >
reserve ( size_type current_size, size_type desired_capacity )
{
const size_type current_capacity = capacity_;
capacity_ = std::max( desired_capacity, capacity_ );
return std::make_pair( current_capacity, capacity_ );
}
std::pair< size_type, size_type >
resize ( size_type current_size, size_type desired_size )
{
if( capacity_ == size_type( 0 ) )
return std::make_pair( size_type( 0 ), capacity_ = desired_size );
const size_type current_capacity = capacity_;
while( desired_size > capacity_ )
capacity_ *= size_type( 2 );
return std::make_pair( current_capacity, capacity_ );
}
private:
size_type capacity_;
};
// StaticCapacityManager
// ---------------------
template< class sz_t = std::size_t >
class StaticCapacityManager
{
typedef StaticCapacityManager< sz_t > This;
public:
typedef sz_t size_type;
template< class _sz_t >
struct rebind { typedef StaticCapacityManager< _sz_t > other; };
StaticCapacityManager () {}
template< class _sz_t >
StaticCapacityManager ( const StaticCapacityManager< _sz_t > & ) {}
StaticCapacityManager ( const This & ) {}
template< class _sz_t >
const This &operator= ( const StaticCapacityManager< _sz_t > & ) { return *this; }
const This &operator= ( const This & ) { return *this; }
size_type capacity ( size_type current_size ) const { return current_size; }
std::pair< size_type, size_type >
reserve ( size_type current_size, size_type desired_capacity )
{
return std::make_pair( current_size, current_size );
}
std::pair< size_type, size_type >
resize ( size_type current_size, size_type desired_size )
{
return std::make_pair( current_size, desired_size );
}
};
// DynamicArray
// ------------
template< class T, class CM = CapacityManager<>, class A = std::allocator< T > >
class DynamicArray
{
typedef DynamicArray< T, CM, A > This;
typedef typename A::template rebind< T >::other my_allocator_type;
public:
typedef T value_type;
typedef CM capacity_manager_type;
typedef A allocator_type;
typedef typename my_allocator_type::const_pointer const_pointer;
typedef typename my_allocator_type::pointer pointer;
typedef typename my_allocator_type::const_reference const_reference;
typedef typename my_allocator_type::reference reference;
typedef typename my_allocator_type::difference_type difference_type;
typedef typename my_allocator_type::size_type size_type;
typedef const_pointer const_iterator;
typedef pointer iterator;
typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
typedef std::reverse_iterator< iterator > reverse_iterator;
private:
typedef typename CM::template rebind< size_type >::other my_capacity_manager_type;
struct Storage
: public my_capacity_manager_type
{
explicit Storage ( const my_capacity_manager_type &capacity_manager )
: my_capacity_manager_type( capacity_manager ), begin( nullptr ), end( nullptr )
{}
pointer begin, end;
};
struct Impl
: public my_allocator_type
{
Impl ( const my_capacity_manager_type &capacity_manager, const my_allocator_type &allocator )
: my_allocator_type( allocator ), storage( capacity_manager )
{}
Storage storage;
};
public:
explicit DynamicArray ( const capacity_manager_type &capacity_manager = capacity_manager_type(),
const allocator_type &allocator = allocator_type() )
: impl_( capacity_manager, allocator )
{
initialize( size_type( 0 ) );
}
explicit DynamicArray ( size_type size, const value_type &value = value_type(),
const capacity_manager_type &capacity_manager = capacity_manager_type(),
const allocator_type &allocator = allocator_type() )
: impl_( capacity_manager, allocator )
{
initialize( size ); construct( value );
}
template< class InputIterator >
DynamicArray ( InputIterator first, InputIterator last,
const capacity_manager_type &capacity_manager = capacity_manager_type(),
const allocator_type &allocator = allocator_type() )
: impl_( capacity_manager, allocator )
{
initialize( std::distance( first, last ) ); construct( first, last );
}
DynamicArray ( const This &other )
: impl_( other.capacity_manager(), other.allocator() )
{
initialize( other.size() ); construct( other.begin(), other.end() );
}
~DynamicArray () { destroy(); deallocate( capacity_manager().capacity( size() ) ); }
const This &operator= ( const This &other )
{
destroy();
capacity_manager() = other.capacity_manager();
initialize( other.size() );
construct( other.begin(), other.end() );
return *this;
}
void assign ( size_type size, const value_type &value )
{
reinitialize( size );
construct( value );
}
template< class InputIterator >
void assign ( InputIterator first, InputIterator last )
{
reinitialize( std::distance( first, last ) );
construct( first, last );
}
void clear () { reinitialize( size_type( 0 ) ); }
void swap ( This &other )
{
std::swap( storage().begin, other.storage().begin );
std::swap( storage().end, other.storage().end );
std::swap( capacity_manager(), other.capacity_manager() );
std::swap( allocator(), other.allocator() );
}
const_reference back () const { assert( !empty ); return *(storage().end-1); }
reference back () { assert( !empty ); return *(storage.end-1); }
const_reference front () const { assert( !empty ); return *storage.begin; }
reference front () { assert( !empty ); return *storage.begin; }
const_reference operator[] ( size_type i ) const { assert( i < size() ); return *(storage().begin+i); }
reference operator[] ( size_type i ) { assert( i < size() ); return *(storage().begin+i); }
const_reference at ( size_type i ) const { rangeCheck( i ); return (*this)[ i ]; }
reference at ( size_type i ) { rangeCheck( i ); return (*this)[ i ]; }
const_iterator begin () const { return const_iterator( storage().begin ); }
iterator begin () { return iterator( storage().begin ); }
const_iterator end () const { return const_iterator( storage().end ); }
iterator end () { return iterator( storage().end ); }
const_reverse_iterator rbegin () const { return const_reverse_iterator( end() ); }
reverse_iterator rbegin () { return reverse_iterator( end() ); }
const_reverse_iterator rend () const { return const_reverse_iterator( begin() ); }
reverse_iterator rend () { return reverse_iterator( begin() ); }
size_type capacity () const { return capacity_manager().capacity( size() ); }
bool empty () const { return (storage().begin == storage().end); }
size_type max_size () const { return allocator().max_size(); }
void reserve ( size_type capacity ) { reallocate( capacity_manager().reserve( size(), capacity ) ); }
void resize ( size_type size, const value_type &value = value_type() );
size_type size () const { return (storage().end - storage().begin); }
allocator_type get_allocator () const { return allocator(); }
protected:
const my_allocator_type &allocator () const { return impl_; }
my_allocator_type &allocator () { return impl_; }
const Storage &storage () const { return impl_.storage; }
Storage &storage () { return impl_.storage; }
const my_capacity_manager_type &capacity_manager () const { storage(); }
my_capacity_manager_type &capacity_manager () { return storage(); }
void allocate ( size_type capacity )
{
storage().begin = (capacity != size_type( 0 ) ? allocator().allocate( capacity ) : nullptr);
}
void reallocate ( std::pair< size_type, size_type > capacity );
void deallocate ( size_type capacity )
{
if( storage().begin )
allocator().deallocate( storage().begin, capacity );
}
void reinitialize ( size_type desired_size )
{
destroy();
std::pair< size_type, size_type > capacity = capacity_manager().resize( size(), desired_size );
if( capacity.first != capacity.second )
{
deallocate( capacity.first );
allocate( capacity.second );
}
storage().end = storage().begin + desired_size;
}
void initialize ( size_type desired_size )
{
allocate( capacity_manager().resize( size_type( 0 ), desired_size ).second );
storage().end = storage().begin + desired_size;
}
void construct ( const value_type &value )
{
for( pointer it = storage().begin; it != storage().end; ++it )
allocator().construct( it, value );
}
template< class InputIterator >
void construct ( InputIterator first, InputIterator last )
{
for( pointer it = storage().begin; it != storage().end; ++it, ++first )
allocator().construct( it, *first );
assert( first == last );
}
void destroy ()
{
for( pointer it = storage().begin; it != storage().end; ++it )
allocator().destroy( it );
}
void rangeCheck ( size_type i ) const
{
if( i >= size() )
DUNE_THROW( RangeError, "Out of range: i = " << i << " >= " << size() << " = size()." );
}
private:
Impl impl_;
};
// Comparison Operators
// --------------------
template< class T, class CM, class A >
inline bool operator== ( const DynamicArray< T, CM, A > &a, const DynamicArray< T, CM, A > &b )
{
return (a.size() == b.size()) && std::equal( a.begin(), a.end(), b.begin() );
}
template< class T, class CM, class A >
inline bool operator!= ( const DynamicArray< T, CM, A > &a, const DynamicArray< T, CM, A > &b )
{
return !(a == b);
}
// Implementation of DynamicArray
// ------------------------------
template< class T, class CM, class A >
inline void DynamicArray< T, CM, A >
::reallocate ( std::pair< size_type, size_type > capacity )
{
if( capacity.first != capacity.second )
{
pointer current_begin = storage().begin;
pointer current_end = storage().end;
allocate( capacity.second );
pointer wit = storage().begin;
for( pointer rit = current_begin; rit != current_end; ++wit, ++rit )
{
allocator().construct( wit, *rit );
allocator().destory( rit );
}
storage().end = wit;
allocator().destroy( current_begin, capacity.first );
}
}
template< class T, class CM, class A >
inline void DynamicArray< T, CM, A >
::resize ( size_type size, const value_type &value )
{
const size_type current_size = (storage().end - storage().begin);
if( size < current_size )
{
for( pointer it = storage().begin + size; it != storage().end; ++it )
allocator().destroy( it );
storage().end = storage().begin + size;
reallocate( capacity_manager.resize( current_size, size ) );
}
else if( size > current_size )
{
reallocate( capacity_manager.resize( current_size, size ) );
storage().end = storage().begin + size;
for( pointer it = storage().begin + current_size; it != storage().end; ++it )
allocator().construct( it, value );
}
}
} // namespace Dune
#endif // #ifndef DUNE_DYNAMICARRAY_HH
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifndef DUNE_STATICARRAY_HH
#define DUNE_STATICARRAY_HH
#include <cassert>
#include <memory>
#include <dune/common/nullptr.hh>
namespace Dune
{
template< class T, class A = std::allocator< T > >
class StaticArray
{
typedef StaticArray< T, A > This;
typedef typename A::template rebind< T >::other TAllocator;
struct Storage
: public TAllocator
{
explicit Storage ( const TAllocator &allocator )
: TAllocator( allocator ), begin( nullptr ), end( nullptr )
{}
typename TAllocator::pointer begin;
typename TAllocator::pointer end;
};
public:
typedef T value_type;
typedef A allocator_type;
typedef typename TAllocator::const_pointer const_pointer;
typedef typename TAllocator::pointer pointer;
typedef typename TAllocator::const_reference const_reference;
typedef typename TAllocator::reference reference;
typedef typename TAllocator::difference_type difference_type;
typedef typename TAllocator::size_type size_type;
typedef const_pointer const_iterator;
typedef pointer iterator;
typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
typedef std::reverse_iterator< iterator > reverse_iterator;
explicit StaticArray ( const allocator_type &allocator = allocator_type() )
: storage_( allocator )
{}
explicit StaticArray ( size_type size, const value_type &value = value_type(),
const allocator_type &allocator = allocator_type() )
: storage_( allocator )
{
allocate( size ); construct( value );
}
template< class InputIterator >
StaticArray ( InputIterator first, InputIterator last, const allocator_type &allocator = allocator_type() )
: storage_( allocator )
{
allocate( std::distance( first, last ) ); construct( first, last );
}
StaticArray ( const This &other )
: storage_( other.allocator() )
{
allocate( other.size() ); construct( other.begin(), other.end() );
}
~StaticArray () { destroy(); deallocate(); }
const This &operator= ( const This &other )
{
destroy(); reallocate( other.size() ); construct( other.begin(), other.end() );
return *this;
}
void assign ( size_type size, const value_type &value )
{
destroy(); reallocate( size ); construct( value );
}
template< class InputIterator >
void assign ( InputIterator first, InputIterator last )
{
destroy(); reallocate( std::distance( first, last ) ); construct( first, last );
}
void clear ()
{
destroy(); deallocate();
storage_.begin = storage_.end = nullptr;
}
void resize ( size_type size, const value_type &value = value_type() );
void swap ( This &other )
{
std::swap( allocator(), other.allocator() );
std::swap( storage_.begin, other.storage_.begin );
std::swap( storage_.end, other.storage_.end );
}
const_reference back () const { assert( !empty ); return *(storage_.end-1); }
reference back () { assert( !empty ); return *(storage_.end-1); }
const_reference front () const { assert( !empty ); return *storage_.begin; }
reference front () { assert( !empty ); return *storage_.begin; }
const_reference operator[] ( size_type i ) const { assert( i < size() ); return *(storage_.begin+i); }
reference operator[] ( size_type i ) { assert( i < size() ); return *(storage_.begin+i); }
const_reference at ( size_type i ) const { rangeCheck( i ); return (*this)[ i ]; }
reference at ( size_type i ) { rangeCheck( i ); return (*this)[ i ]; }
const_iterator begin () const { return const_iterator( storage_.begin ); }
iterator begin () { return iterator( storage_.begin ); }
const_iterator end () const { return const_iterator( storage_.end ); }
iterator end () { return iterator( storage_.end ); }
const_reverse_iterator rbegin () const { return const_reverse_iterator( end() ); }
reverse_iterator rbegin () { return reverse_iterator( end() ); }
const_reverse_iterator rend () const { return const_reverse_iterator( begin() ); }
reverse_iterator rend () { return reverse_iterator( begin() ); }
bool empty () const { return (storage_.begin == storage_.end); }
size_type size () const { return storage_.end - storage_.begin; }
allocator_type get_allocator () const { return allocator(); }
size_type max_size () const { return allocator().max_size(); }
protected:
const TAllocator &allocator () const { return static_cast< const TAllocator & >( storage_ ); }
TAllocator &allocator () { return static_cast< TAllocator & >( storage_ ); }
void allocate ( size_type size )
{
storage_.begin = (size != size_type( 0 ) ? allocator().allocate( size ) : nullptr);
storage_.end = storage_.begin + size;
}
void reallocate ( size_type size )
{
if( storage_.begin + size != storage_.end )
{
deallocate();
allocate( size );
}
}
void deallocate ()
{
if( storage_.begin )
allocator().deallocate( storage_.begin, size() );
}
void construct ( const value_type &value )
{
for( pointer it = storage_.begin; it != storage_.end; ++it )
allocator().construct( it, value );
}
template< class InputIterator >
void construct ( InputIterator first, InputIterator last )
{
for( pointer it = storage_.begin; it != storage_.end; ++it, ++first )
allocator().construct( it, *first );
assert( first == last );
}
void destroy ()
{
for( pointer it = storage_.begin; it != storage_.end; ++it )
allocator().destroy( it );
}
private:
Storage storage_;
};
// Comparison Operators
// --------------------
template< class T, class A >
inline bool operator== ( const StaticArray< T, A > &a, const StaticArray< T, A > &b )
{
return (a.size() == b.size()) && std::equal( a.begin(), a.end(), b.begin() );
}
template< class T, class A >
inline bool operator!= ( const StaticArray< T, A > &a, const StaticArray< T, A > &b )
{
return !(a == b);
}
// Implementation of StaticArray
// -----------------------------
template< class T, class A >
inline void StaticArray< T, A >::resize ( size_type size, const value_type &value )
{
if( storage_.begin + size != storage_.end )
{
const pointer oldBegin = storage_.begin;
const pointer oldEnd = storage_.end;
const pointer copyEnd = oldBegin + std::min( size, oldEnd - oldBegin );
storage_.begin = allocate( size );
storage_.end = storage_.begin + size;
pointer it = storage_.begin;
for( pointer oldIt = oldBegin; oldIt != copyEnd; ++it, ++oldIt )
{
allocator().construct( it, *oldIt );
allocator().destroy( oldIt );
}
for( ; it != end; ++it )
allocator().construct( it, value );
for( pointer oldIt = copyEnd; oldIt != oldEnd; ++oldIt )
allocator().destroy( oldIt );
}
}
} // namespace Dune
#endif // #ifndef DUNE_STATICARRAY_HH
arraytest
arraylisttest
bitsetvectortest
dynamicarraytest
sllisttest
staticarraytest
......
# -*- tab-width: 8; indent-tabs-mode: nil -*-
TESTPROGS = arraytest arraylisttest bitsetvectortest sllisttest staticarraytest
TESTPROGS = arraytest arraylisttest bitsetvectortest dynamicarraytest sllisttest
# programs to run when "make check" is used
TESTS = $(TESTPROGS)
......@@ -13,8 +13,8 @@ arraylisttest_SOURCES = arraylisttest.cc
bitsetvectortest_SOURCES = bitsetvectortest.cc
sllisttest_SOURCES = sllisttest.cc
dynamicarraytest_SOURCES = dynamicarraytest.cc
staticarraytest_SOURCES = staticarraytest.cc
sllisttest_SOURCES = sllisttest.cc
include $(top_srcdir)/am/global-rules
......@@ -6,15 +6,22 @@
#include <iostream>
#include <dune/common/container/staticarray.hh>
#include <dune/common/container/dynamicarray.hh>
int main ( int argc, char **argv )
{
std::cout << "sizeof( Dune::StaticArray< int > ) = " << sizeof( Dune::StaticArray< int > ) << std::endl;
std::cout << "sizeof( Dune::DynamicArray< int > ) = " << sizeof( Dune::DynamicArray< int > ) << std::endl;
Dune::StaticArray< int > a( 4 );
std::cout << "sizeof( Dune::DynamicArray< int, Dune::StaticCapacityManager<> > ) = "
<< sizeof( Dune::DynamicArray< int, Dune::StaticCapacityManager<> > ) << std::endl;
Dune::DynamicArray< int > a( 4 );
for( int i = 0; i < 4; ++i )
a[ i ] = i+20;
Dune::DynamicArray< int, Dune::StaticCapacityManager<> > b( 4 );
for( int i = 0; i < 4; ++i )
b[ i ] = a[ i ] + 20;
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment