DeckItem without internal inheritance.

Replaces the internal inheritance + unique_ptr scheme to a flat sum type
similar scheme that uses a tag to determine which operations are legal,
rather than using the indirection itself as a tag.
This commit is contained in:
Jørgen Kvalsvik
2016-10-23 15:53:36 +02:00
parent 9511d8252b
commit fdb772e075
15 changed files with 269 additions and 572 deletions

View File

@@ -26,367 +26,211 @@
namespace Opm {
template< typename T >
class DeckTypeItem : public DeckItemBase {
public:
const std::string& name() const override;
bool defaultApplied( size_t ) const override;
bool hasValue( size_t ) const override;
size_t size() const override;
template< typename T >
std::vector< T >& DeckItem::value_ref() {
return const_cast< std::vector< T >& >(
const_cast< const DeckItem& >( *this ).value_ref< T >()
);
}
void push_back( T );
void push_back( T, size_t numValues );
void push_backDefault( T );
void push_backDummyDefault() override;
template<>
const std::vector< int >& DeckItem::value_ref< int >() const {
if( this->type != get_type< int >() )
throw std::invalid_argument( "Item of wrong type." );
const T& get( size_t ) const;
const std::vector< T >& getData() const;
return this->ival;
}
protected:
DeckTypeItem( const std::string&, size_t );
template<>
const std::vector< double >& DeckItem::value_ref< double >() const {
if( this->type != get_type< double >() )
throw std::invalid_argument( "Item of wrong type." );
private:
std::string item_name;
std::vector< bool > dataPointDefaulted;
std::vector< T > data;
};
return this->dval;
}
template< typename T >
class DeckItemT : public DeckTypeItem< T > {
private:
using DeckTypeItem< T >::DeckTypeItem;
std::unique_ptr< DeckItemBase > clone() const override;
template<>
const std::vector< std::string >& DeckItem::value_ref< std::string >() const {
if( this->type != get_type< std::string >() )
throw std::invalid_argument( "Item of wrong type." );
friend class DeckItem;
};
return this->sval;
}
template<>
class DeckItemT< double > : public DeckTypeItem< double > {
public:
using DeckTypeItem< double >::DeckTypeItem;
DeckItem::DeckItem( const std::string& nm ) : item_name( nm ) {}
const double& getSI( size_t ) const;
const std::vector< double >& getSIData() const;
DeckItem::DeckItem( const std::string& nm, int, size_t hint ) :
type( get_type< int >() ),
item_name( nm )
{
this->ival.reserve( hint );
this->defaulted.reserve( hint );
}
void push_backDimension( const Dimension& activeDimension,
const Dimension& defaultDimension );
DeckItem::DeckItem( const std::string& nm, double, size_t hint ) :
type( get_type< double >() ),
item_name( nm )
{
this->dval.reserve( hint );
this->defaulted.reserve( hint );
}
private:
const std::vector< double >& assertSIData() const;
std::unique_ptr< DeckItemBase > clone() const override;
DeckItem::DeckItem( const std::string& nm, std::string, size_t hint ) :
type( get_type< std::string >() ),
item_name( nm )
{
this->sval.reserve( hint );
this->defaulted.reserve( hint );
}
mutable std::vector< double > SIdata;
std::vector< Dimension > dimensions;
const std::string& DeckItem::name() const {
return this->item_name;
}
friend class DeckItem;
};
bool DeckItem::defaultApplied( size_t index ) const {
return this->defaulted.at( index );
}
template< typename T > static inline DeckItem::type type_to_tag();
template<>
DeckItem::type type_to_tag< int >() {
return DeckItem::integer;
bool DeckItem::hasValue( size_t index ) const {
switch( this->type ) {
case type_tag::integer: return this->ival.size() > index;
case type_tag::fdouble: return this->dval.size() > index;
case type_tag::string: return this->sval.size() > index;
default: throw std::logic_error( "Type not set." );
}
}
template<>
DeckItem::type type_to_tag< double >() {
return DeckItem::fdouble;
size_t DeckItem::size() const {
switch( this->type ) {
case type_tag::integer: return this->ival.size();
case type_tag::fdouble: return this->dval.size();
case type_tag::string: return this->sval.size();
default: throw std::logic_error( "Type not set." );
}
}
template<>
DeckItem::type type_to_tag< std::string >() {
return DeckItem::string;
}
template< typename T >
const T& DeckItem::get( size_t index ) const {
return this->value_ref< T >().at( index );
}
static inline std::string tag_to_string( DeckItem::type x ) {
switch( x ) {
case DeckItem::type::integer: return "int";
case DeckItem::type::string: return "std::string";
case DeckItem::type::fdouble: return "double";
case DeckItem::type::unknown: return "unknown";
template< typename T >
const std::vector< T >& DeckItem::getData() const {
return this->value_ref< T >();
}
}
return "unknown";
}
template< typename T >
void DeckItem::push( T x, size_t n ) {
auto& val = this->value_ref< T >();
val.insert( val.end(), n, x );
this->defaulted.insert( this->defaulted.end(), n, false );
}
void DeckItem::push_back( int x, size_t n ) {
this->push( x, n );
}
void DeckItem::push_back( double x, size_t n ) {
this->push( x, n );
}
void DeckItem::push_back( std::string x, size_t n ) {
this->push( std::move( x ), n );
}
template< typename T >
void DeckItem::push_default( T x ) {
auto& val = this->value_ref< T >();
if( this->defaulted.size() != val.size() )
throw std::logic_error("To add a value to an item, "
"no 'pseudo defaults' can be added before");
val.push_back( std::move( x ) );
this->defaulted.push_back( true );
}
void DeckItem::push_backDefault( int x ) {
this->push_default( x );
}
void DeckItem::push_backDefault( double x ) {
this->push_default( x );
}
void DeckItem::push_backDefault( std::string x ) {
this->push_default( std::move( x ) );
}
template< typename T >
DeckTypeItem< T >::DeckTypeItem( const std::string& nm, size_t sz ) :
DeckItemBase( type_to_tag< T >() ),
item_name( nm )
{
this->dataPointDefaulted.reserve( sz );
this->data.reserve( sz );
}
void DeckItem::push_backDummyDefault() {
if( !this->defaulted.empty() )
throw std::logic_error("Pseudo defaults can only be specified for empty items");
template< typename T >
const std::string& DeckTypeItem< T >::name() const {
return this->item_name;
}
this->defaulted.push_back( true );
}
template< typename T >
bool DeckTypeItem< T >::defaultApplied( size_t index ) const {
return this->dataPointDefaulted.at( index );
}
std::string DeckItem::getTrimmedString( size_t index ) const {
return boost::algorithm::trim_copy(
this->value_ref< std::string >().at( index )
);
}
template< typename T >
bool DeckTypeItem< T >::hasValue( size_t index ) const {
return index < this->size();
}
double DeckItem::getSIDouble( size_t index ) const {
return this->getSIDoubleData().at( index );
}
template< typename T >
size_t DeckTypeItem< T >::size() const {
return this->data.size();
}
const std::vector< double >& DeckItem::getSIDoubleData() const {
const auto& raw = this->value_ref< double >();
// we already converted this item to SI?
if( !this->SIdata.empty() ) return this->SIdata;
template< typename T >
void DeckTypeItem< T >::push_back( T x ) {
if( this->dataPointDefaulted.size() != this->data.size() )
throw std::logic_error("To add a value to an item, no \"pseudo defaults\" can be added before");
this->data.push_back( x );
this->dataPointDefaulted.push_back( false );
}
template< typename T >
void DeckTypeItem< T >::push_backDefault( T data_arg ) {
if( this->dataPointDefaulted.size() != this->data.size() )
throw std::logic_error("To add a value to an item, no \"pseudo defaults\" can be added before");
this->data.push_back( data_arg );
this->dataPointDefaulted.push_back(true);
}
template< typename T >
void DeckTypeItem< T >::push_backDummyDefault() {
if( this->dataPointDefaulted.size() != 0 )
throw std::logic_error("Pseudo defaults can only be specified for empty items");
this->dataPointDefaulted.push_back( true );
}
template< typename T >
void DeckTypeItem< T >::push_back( T x, size_t numValues ) {
if( this->dataPointDefaulted.size() != this->data.size() )
throw std::logic_error("To add a value to an item, no \"pseudo defaults\" can be added before");
this->data.insert( this->data.end(), numValues, x );
this->dataPointDefaulted.insert( this->dataPointDefaulted.end(), numValues, false );
}
template< typename T >
const T& DeckTypeItem< T >::get( size_t index ) const {
return this->data.at( index );
}
template< typename T >
const std::vector< T >& DeckTypeItem< T >::getData() const {
return this->data;
}
const double& DeckItemT< double >::getSI( size_t index ) const {
return this->assertSIData().at( index );
}
const std::vector< double >& DeckItemT< double >::getSIData() const {
return this->assertSIData();
}
void DeckItemT< double >::push_backDimension( const Dimension& activeDimension,
const Dimension& defaultDimension ) {
if( this->size() == 0 || this->defaultApplied( this->size() - 1 ) )
this->dimensions.push_back( defaultDimension );
else
this->dimensions.push_back( activeDimension );
}
template< typename T >
std::unique_ptr< DeckItemBase > DeckItemT< T >::clone() const {
return std::unique_ptr< DeckItemBase > { new DeckItemT< T >( *this ) };
}
std::unique_ptr< DeckItemBase > DeckItemT< double >::clone() const {
return std::unique_ptr< DeckItemBase > { new DeckItemT< double >( *this ) };
}
const std::vector< double >& DeckItemT< double >::assertSIData() const {
// we already converted this item to SI?
if( !this->SIdata.empty() ) return this->SIdata;
if( this->dimensions.empty() )
throw std::invalid_argument("No dimension has been set for item:" + this->name() + " can not ask for SI data");
/*
* This is an unobservable state change - SIData is lazily converted to
* SI units, so externally the object still behaves as const
*/
const auto dim_size = dimensions.size();
const auto sz = this->size();
this->SIdata.resize( sz );
for( size_t index = 0; index < sz; index++ ) {
const auto dimIndex = index % dim_size;
this->SIdata[ index ] = this->dimensions[ dimIndex ]
.convertRawToSi( this->get( index ) );
}
return this->SIdata;
}
template< typename T >
static inline DeckItemT< T >* conv( std::unique_ptr< DeckItemBase >& ptr ) {
if( ptr->type_tag == type_to_tag< T >() )
return static_cast< DeckItemT< T >* >( ptr.get() );
throw std::logic_error(
"Treating item " + ptr->name()
+ " as " + tag_to_string( type_to_tag< T >() )
+ ", but is "
+ tag_to_string( ptr->type_tag ) );
}
template< typename T >
static inline
const DeckItemT< T >* conv( const std::unique_ptr< DeckItemBase >& ptr ) {
if( ptr->type_tag == type_to_tag< T >() )
return static_cast< const DeckItemT< T >* >( ptr.get() );
throw std::logic_error(
"Treating item " + ptr->name()
+ " as " + tag_to_string( type_to_tag< T >() )
+ ", but is "
+ tag_to_string( ptr->type_tag ) );
}
DeckItem::DeckItem( const DeckItem& rhs ) :
ptr( rhs.ptr->clone() )
{}
DeckItem::DeckItem( std::unique_ptr< DeckItemBase >&& x ) :
ptr( std::move( x ) )
{}
template< typename T >
DeckItem DeckItem::make( const std::string& name, size_t size ) {
return DeckItem( std::unique_ptr< DeckItemBase > { new DeckItemT< T >( name, size ) } );
}
const std::string& DeckItem::name() const {
return this->ptr->name();
}
bool DeckItem::defaultApplied( size_t index ) const {
return this->ptr->defaultApplied( index );
}
bool DeckItem::hasValue( size_t index ) const {
return this->ptr->hasValue( index );
}
size_t DeckItem::size() const {
return this->ptr->size();
}
template< typename T >
const T& DeckItem::get( size_t index ) const {
return conv< T >( this->ptr )->get( index );
}
template< typename T >
const std::vector< T >& DeckItem::getData() const {
return conv< T >( this->ptr )->getData();
}
template< typename T >
void DeckItem::push_back( T x ) {
return conv< T >( this->ptr )->push_back( x );
}
template< typename T >
void DeckItem::push_back( T x, size_t n ) {
return conv< T >( this->ptr )->push_back( x, n );
}
template< typename T >
void DeckItem::push_backDefault( T x ) {
return conv< T >( this->ptr )->push_backDefault( x );
}
template<>
void DeckItem::push_back( const char* x ) {
return conv< std::string >( this->ptr )->push_back( x );
}
template<>
void DeckItem::push_back( const char* x, size_t n ) {
return conv< std::string >( this->ptr )->push_back( x, n );
}
template<>
void DeckItem::push_backDefault( const char* x ) {
return conv< std::string >( this->ptr )->push_backDefault( x );
}
void DeckItem::push_backDummyDefault() {
return this->ptr->push_backDummyDefault();
}
std::string DeckItem::getTrimmedString( size_t index ) const {
return boost::algorithm::trim_copy(
conv< std::string >( this->ptr )->get( index )
);
}
double DeckItem::getSIDouble( size_t index ) const {
return conv< double >( this->ptr )->getSI( index );
}
const std::vector< double >& DeckItem::getSIDoubleData() const {
return conv< double >( this->ptr )->getSIData();
}
void DeckItem::push_backDimension( Dimension active,
Dimension def ) {
return conv< double >( this->ptr ) ->push_backDimension( active, def );
}
DeckItem::type DeckItem::getType() const {
return this->ptr->type_tag;
}
if( this->dimensions.empty() )
throw std::invalid_argument("No dimension has been set for item'"
+ this->name()
+ "'; can not ask for SI data");
/*
* Explicit template instantiations. These must be manually maintained and
* updated with changes in DeckItem so that code is emitted.
* This is an unobservable state change - SIData is lazily converted to
* SI units, so externally the object still behaves as const
*/
const auto dim_size = dimensions.size();
const auto sz = raw.size();
this->SIdata.resize( sz );
template class DeckTypeItem< int >;
template class DeckTypeItem< double >;
template class DeckTypeItem< std::string >;
for( size_t index = 0; index < sz; index++ ) {
const auto dimIndex = index % dim_size;
this->SIdata[ index ] = this->dimensions[ dimIndex ]
.convertRawToSi( raw[ index ] );
}
template class DeckItemT< int >;
template class DeckItemT< double >;
template class DeckItemT< std::string >;
return this->SIdata;
}
template DeckItem DeckItem::make< int >( const std::string&, size_t );
template DeckItem DeckItem::make< double >( const std::string&, size_t );
template DeckItem DeckItem::make< std::string >( const std::string&, size_t );
void DeckItem::push_backDimension( const Dimension& active,
const Dimension& def ) {
const auto& ds = this->value_ref< double >();
const bool dim_inactive = ds.empty()
|| this->defaultApplied( ds.size() - 1 );
template const int& DeckItem::get< int >( size_t ) const;
template const double& DeckItem::get< double >( size_t ) const;
template const std::string& DeckItem::get< std::string >( size_t ) const;
this->dimensions.push_back( dim_inactive ? def : active );
}
template const std::vector< int >& DeckItem::getData< int >() const;
template const std::vector< double >& DeckItem::getData< double >() const;
template const std::vector< std::string >& DeckItem::getData< std::string >() const;
type_tag DeckItem::getType() const {
return this->type;
}
template void DeckItem::push_back< int >( int );
template void DeckItem::push_back< double >( double );
template void DeckItem::push_back< std::string >( std::string );
template void DeckItem::push_back< int >( int, size_t );
template void DeckItem::push_back< double >( double, size_t );
template void DeckItem::push_back< std::string >( std::string, size_t );
template void DeckItem::push_backDefault< int >( int );
template void DeckItem::push_backDefault< double >( double );
template void DeckItem::push_backDefault< std::string >( std::string );
/*
* Explicit template instantiations. These must be manually maintained and
* updated with changes in DeckItem so that code is emitted.
*/
template const int& DeckItem::get< int >( size_t ) const;
template const double& DeckItem::get< double >( size_t ) const;
template const std::string& DeckItem::get< std::string >( size_t ) const;
template const std::vector< int >& DeckItem::getData< int >() const;
template const std::vector< double >& DeckItem::getData< double >() const;
template const std::vector< std::string >& DeckItem::getData< std::string >() const;
}

View File

@@ -25,29 +25,18 @@
#include <memory>
#include <opm/parser/eclipse/Units/Dimension.hpp>
#include <opm/parser/eclipse/Utility/Typetools.hpp>
namespace Opm {
class DeckItem;
class DeckItemBase;
class DeckItem {
public:
DeckItem() = delete;
DeckItem( const DeckItem& );
DeckItem() = default;
DeckItem( const std::string& );
/* for python interop as well as queries, must be manually synchronised
* with cdeck_item.cc and opm/deck/item_type_enum.py
*/
enum type {
unknown = 0, /* this signals an error */
integer = 1,
string = 2,
fdouble = 3
};
template< typename T >
static DeckItem make( const std::string&, size_t = 1 );
DeckItem( const std::string&, int, size_t size_hint = 8 );
DeckItem( const std::string&, double, size_t size_hint = 8 );
DeckItem( const std::string&, std::string, size_t size_hint = 8 );
const std::string& name() const;
@@ -73,40 +62,37 @@ namespace Opm {
template< typename T > const std::vector< T >& getData() const;
const std::vector< double >& getSIDoubleData() const;
template< typename T > void push_back( T );
template< typename T > void push_back( T, size_t );
template< typename T > void push_backDefault( T );
void push_back( int, size_t = 1 );
void push_back( double, size_t = 1 );
void push_back( std::string, size_t = 1 );
void push_backDefault( int );
void push_backDefault( double );
void push_backDefault( std::string );
// trying to access the data of a "dummy default item" will raise an exception
void push_backDummyDefault();
void push_backDimension( Dimension /* activeDimension */,
Dimension /* defaultDimension */);
void push_backDimension( const Dimension& /* activeDimension */,
const Dimension& /* defaultDimension */);
type getType() const;
type_tag getType() const;
private:
DeckItem( std::unique_ptr< DeckItemBase >&& );
std::unique_ptr< DeckItemBase > ptr;
std::vector< double > dval;
std::vector< int > ival;
std::vector< std::string > sval;
type_tag type = type_tag::unknown;
std::string item_name;
std::vector< bool > defaulted;
std::vector< Dimension > dimensions;
mutable std::vector< double > SIdata;
template< typename T > std::vector< T >& value_ref();
template< typename T > const std::vector< T >& value_ref() const;
template< typename T > void push( T, size_t );
template< typename T > void push_default( T );
};
class DeckItemBase {
public:
virtual const std::string& name() const = 0;
virtual bool defaultApplied( size_t ) const = 0;
virtual bool hasValue( size_t ) const = 0;
virtual size_t size() const = 0;
virtual void push_backDummyDefault() = 0;
virtual ~DeckItemBase() = default;
const DeckItem::type type_tag;
protected:
DeckItemBase( DeckItem::type tag ) : type_tag( tag ) {}
private:
virtual std::unique_ptr< DeckItemBase > clone() const = 0;
friend class DeckItem;
};
}
#endif /* DECKITEM_HPP */

View File

@@ -56,7 +56,7 @@ namespace Opm {
return m_items.size();
}
void DeckRecord::addItem( DeckItem&& deckItem ) {
void DeckRecord::addItem( DeckItem deckItem ) {
if( this->hasItem( deckItem.name() ) )
throw std::invalid_argument(
"Item with name: "

View File

@@ -36,7 +36,7 @@ namespace Opm {
DeckRecord( std::vector< DeckItem >&& );
size_t size() const;
void addItem( DeckItem&& deckItem );
void addItem( DeckItem deckItem );
DeckItem& getItem( size_t index );
DeckItem& getItem( const std::string& name );
@@ -47,7 +47,7 @@ namespace Opm {
const DeckItem& getDataItem() const;
bool hasItem(const std::string& name) const;
template <class Item>
DeckItem& getItem() {
return getItem( Item::itemName );

View File

@@ -30,11 +30,11 @@
using namespace Opm;
BOOST_AUTO_TEST_CASE(InitializeDouble) {
BOOST_REQUIRE_NO_THROW( DeckItem::make< double >("HEI") );
BOOST_REQUIRE_NO_THROW( DeckItem( "HEI", double() ) );
}
BOOST_AUTO_TEST_CASE(GetDoubleAtIndex_NoData_ExceptionThrown) {
auto deckDoubleItem = DeckItem::make< double >("TEST");
DeckItem deckDoubleItem( "TEST", double() );
BOOST_CHECK_THROW(deckDoubleItem.get< double >(0), std::out_of_range);
deckDoubleItem.push_back(1.89);
@@ -43,7 +43,7 @@ BOOST_AUTO_TEST_CASE(GetDoubleAtIndex_NoData_ExceptionThrown) {
BOOST_AUTO_TEST_CASE(sizeDouble_correct) {
auto deckDoubleItem = DeckItem::make< double >("TEST");
DeckItem deckDoubleItem( "TEST", double() );
BOOST_CHECK_EQUAL( 0U , deckDoubleItem.size());
deckDoubleItem.push_back( 100.0 );
@@ -57,7 +57,7 @@ BOOST_AUTO_TEST_CASE(sizeDouble_correct) {
BOOST_AUTO_TEST_CASE(SetInDeck) {
auto deckDoubleItem = DeckItem::make< double >("TEST");
DeckItem deckDoubleItem( "TEST", double() );
BOOST_CHECK( deckDoubleItem.size() == 0 );
deckDoubleItem.push_backDefault( 1.0 );
@@ -74,7 +74,7 @@ BOOST_AUTO_TEST_CASE(SetInDeck) {
}
BOOST_AUTO_TEST_CASE(DummyDefaults) {
auto deckDoubleItem = DeckItem::make< double >("TEST");
DeckItem deckDoubleItem( "TEST", double() );
BOOST_CHECK_EQUAL(deckDoubleItem.size(), 0);
deckDoubleItem.push_backDummyDefault();
@@ -84,7 +84,7 @@ BOOST_AUTO_TEST_CASE(DummyDefaults) {
}
BOOST_AUTO_TEST_CASE(PushBackMultiple) {
auto item = DeckItem::make< double >("HEI");
DeckItem item( "HEI", double() );
item.push_back(10.22 , 100 );
BOOST_CHECK_EQUAL( 100U , item.size() );
for (size_t i=0; i < 100; i++)
@@ -92,7 +92,7 @@ BOOST_AUTO_TEST_CASE(PushBackMultiple) {
}
BOOST_AUTO_TEST_CASE(PushBackDimension) {
auto item = DeckItem::make< double >("HEI");
DeckItem item( "HEI", double() );
Dimension activeDimension{ "Length" , 100 };
Dimension defaultDimension{ "Length" , 10 };
@@ -104,13 +104,13 @@ BOOST_AUTO_TEST_CASE(PushBackDimension) {
}
BOOST_AUTO_TEST_CASE(PushBackDimensionInvalidType) {
auto item = DeckItem::make< int >("HEI");
DeckItem item( "HEI", int() );
Dimension dim{ "Length" , 100 };
BOOST_CHECK_THROW( item.push_backDimension( dim , dim ) , std::logic_error );
}
BOOST_AUTO_TEST_CASE(GetSIWithoutDimensionThrows) {
auto item = DeckItem::make< double >("HEI");
DeckItem item( "HEI", double() );
item.push_back(10.22 , 100 );
BOOST_CHECK_THROW( item.getSIDouble(0) , std::invalid_argument );
@@ -118,7 +118,7 @@ BOOST_AUTO_TEST_CASE(GetSIWithoutDimensionThrows) {
}
BOOST_AUTO_TEST_CASE(GetSISingleDimensionCorrect) {
auto item = DeckItem::make< double >("HEI");
DeckItem item( "HEI", double() );
Dimension dim{ "Length" , 100 };
item.push_back(1.0 , 100 );
@@ -129,7 +129,7 @@ BOOST_AUTO_TEST_CASE(GetSISingleDimensionCorrect) {
}
BOOST_AUTO_TEST_CASE(GetSISingleDefault) {
auto item = DeckItem::make< double >("HEI");
DeckItem item( "HEI", double() );
Dimension dim{ "Length" , 1 };
Dimension defaultDim{ "Length" , 100 };
@@ -141,7 +141,7 @@ BOOST_AUTO_TEST_CASE(GetSISingleDefault) {
}
BOOST_AUTO_TEST_CASE(GetSIMultipleDim) {
auto item = DeckItem::make< double >("HEI");
DeckItem item( "HEI", double() );
Dimension dim1{ "Length" , 2 };
Dimension dim2{ "Length" , 4 };
Dimension dim3{ "Length" , 8 };

View File

@@ -27,12 +27,12 @@
using namespace Opm;
BOOST_AUTO_TEST_CASE(Initialize) {
BOOST_REQUIRE_NO_THROW( DeckItem::make< int >("TEST") );
BOOST_REQUIRE_NO_THROW( DeckItem m( "TEST", int() ) );
}
BOOST_AUTO_TEST_CASE(HasValue) {
auto deckIntItem = DeckItem::make< int >("TEST");
DeckItem deckIntItem( "TEST", int() );
BOOST_CHECK_EQUAL( false , deckIntItem.hasValue(0) );
deckIntItem.push_back(1);
BOOST_CHECK_EQUAL( true , deckIntItem.hasValue(0) );
@@ -40,7 +40,7 @@ BOOST_AUTO_TEST_CASE(HasValue) {
}
BOOST_AUTO_TEST_CASE(DummyDefaults) {
auto deckIntItem = DeckItem::make< int >("TEST");
DeckItem deckIntItem( "TEST", int() );
BOOST_CHECK_EQUAL(deckIntItem.size(), 0);
deckIntItem.push_backDummyDefault();
@@ -52,19 +52,19 @@ BOOST_AUTO_TEST_CASE(DummyDefaults) {
}
BOOST_AUTO_TEST_CASE(GetIntAtIndex_NoData_ExceptionThrown) {
auto deckIntItem = DeckItem::make< int >("TEST");
DeckItem deckIntItem( "TEST", int() );
deckIntItem.push_back(100);
BOOST_CHECK(deckIntItem.get< int >(0) == 100);
BOOST_CHECK_THROW(deckIntItem.get< int >(1), std::out_of_range);
}
BOOST_AUTO_TEST_CASE(InitializeDefaultApplied) {
auto deckIntItem = DeckItem::make< int >("TEST");
DeckItem deckIntItem( "TEST", int() );
BOOST_CHECK( deckIntItem.size() == 0 );
}
BOOST_AUTO_TEST_CASE(size_correct) {
auto deckIntItem = DeckItem::make< int >("TEST");
DeckItem deckIntItem( "TEST", int() );
BOOST_CHECK_EQUAL( 0U , deckIntItem.size());
deckIntItem.push_back( 100 );
@@ -76,7 +76,7 @@ BOOST_AUTO_TEST_CASE(size_correct) {
}
BOOST_AUTO_TEST_CASE(DefaultNotApplied) {
auto deckIntItem = DeckItem::make< int >("TEST");
DeckItem deckIntItem( "TEST", int() );
BOOST_CHECK( deckIntItem.size() == 0 );
deckIntItem.push_back( 100 );
@@ -89,7 +89,7 @@ BOOST_AUTO_TEST_CASE(DefaultNotApplied) {
}
BOOST_AUTO_TEST_CASE(UseDefault) {
auto deckIntItem = DeckItem::make< int >("TEST");
DeckItem deckIntItem( "TEST", int() );
deckIntItem.push_backDefault( 100 );
@@ -101,7 +101,7 @@ BOOST_AUTO_TEST_CASE(UseDefault) {
}
BOOST_AUTO_TEST_CASE(DefaultApplied) {
auto deckIntItem = DeckItem::make< int >("TEST");
DeckItem deckIntItem( "TEST", int() );
BOOST_CHECK( deckIntItem.size() == 0 );
deckIntItem.push_backDefault( 100 );
@@ -117,12 +117,9 @@ BOOST_AUTO_TEST_CASE(DefaultApplied) {
BOOST_AUTO_TEST_CASE(PushBackMultiple) {
auto item = DeckItem::make< int >("HEI");
DeckItem item( "HEI", int() );
item.push_back(10 , 100U );
BOOST_CHECK_EQUAL( 100U , item.size() );
for (size_t i=0; i < 100; i++)
BOOST_CHECK_EQUAL(10 , item.get< int >(i));
}

View File

@@ -31,10 +31,6 @@
using namespace Opm;
static DeckItem mkIntItem( std::string name ) {
return DeckItem::make< int >( name );
}
BOOST_AUTO_TEST_CASE(Initialize) {
BOOST_CHECK_NO_THROW(DeckRecord deckRecord);
}
@@ -46,56 +42,49 @@ BOOST_AUTO_TEST_CASE(size_defaultConstructor_sizezero) {
BOOST_AUTO_TEST_CASE(addItem_singleItem_sizeone) {
DeckRecord deckRecord;
deckRecord.addItem( mkIntItem( "TEST" ) );
deckRecord.addItem( DeckItem { "TEST", int() } );
BOOST_CHECK_EQUAL(1U, deckRecord.size());
}
BOOST_AUTO_TEST_CASE(addItem_multipleItems_sizecorrect) {
DeckRecord deckRecord;
deckRecord.addItem( mkIntItem( "TEST" ) );
deckRecord.addItem( mkIntItem( "TEST2" ) );
deckRecord.addItem( mkIntItem( "TEST3" ) );
deckRecord.addItem( DeckItem { "TEST", int() } );
deckRecord.addItem( DeckItem { "TEST2", int() } );
deckRecord.addItem( DeckItem { "TEST3", int() } );
BOOST_CHECK_EQUAL(3U, deckRecord.size());
}
BOOST_AUTO_TEST_CASE(addItem_sameItemTwoTimes_throws) {
DeckRecord deckRecord;
auto intItem1 = mkIntItem( "TEST" );
deckRecord.addItem( std::move( intItem1 ) );
BOOST_CHECK_THROW(deckRecord.addItem( std::move( intItem1 ) ), std::invalid_argument);
}
BOOST_AUTO_TEST_CASE(addItem_differentItemsSameName_throws) {
DeckRecord deckRecord;
deckRecord.addItem( mkIntItem( "TEST" ) );
BOOST_CHECK_THROW( deckRecord.addItem( mkIntItem( "TEST" ) ), std::invalid_argument );
std::vector< DeckItem > items = { mkIntItem( "TEST" ), mkIntItem( "TEST" ) };
deckRecord.addItem( DeckItem { "TEST", int() } );
BOOST_CHECK_THROW( deckRecord.addItem( DeckItem { "TEST", int() } ), std::invalid_argument );
std::vector< DeckItem > items = { DeckItem { "TEST", int() }, DeckItem { "TEST" , int() } };
BOOST_CHECK_THROW( DeckRecord( std::move( items ) ), std::invalid_argument );
}
BOOST_AUTO_TEST_CASE(get_byIndex_returnsItem) {
DeckRecord deckRecord;
deckRecord.addItem( mkIntItem( "TEST" ) );
deckRecord.addItem( DeckItem { "TEST", int() } );
BOOST_CHECK_NO_THROW(deckRecord.getItem(0U));
}
BOOST_AUTO_TEST_CASE(get_indexoutofbounds_throws) {
DeckRecord deckRecord;
deckRecord.addItem( mkIntItem( "TEST" ) );
deckRecord.addItem( DeckItem { "TEST", int() } );
BOOST_CHECK_THROW(deckRecord.getItem(1), std::out_of_range);
}
BOOST_AUTO_TEST_CASE(get_byName_returnsItem) {
DeckRecord deckRecord;
deckRecord.addItem( mkIntItem( "TEST" ) );
deckRecord.addItem( DeckItem { "TEST", int() } );
deckRecord.getItem("TEST");
}
BOOST_AUTO_TEST_CASE(get_byNameNonExisting_throws) {
DeckRecord deckRecord;
deckRecord.addItem( mkIntItem( "TEST" ) );
deckRecord.addItem( DeckItem { "TEST", int() } );
BOOST_CHECK_THROW(deckRecord.getItem("INVALID"), std::invalid_argument);
}

View File

@@ -28,12 +28,12 @@
using namespace Opm;
BOOST_AUTO_TEST_CASE(InitializeString) {
auto stringItem = DeckItem::make< std::string >("TEST");
DeckItem stringItem("TEST", std::string() );
BOOST_CHECK_EQUAL("TEST", stringItem.name());
}
BOOST_AUTO_TEST_CASE(DummyDefaults) {
auto deckStringItem = DeckItem::make< std::string >("TEST");
DeckItem deckStringItem("TEST", std::string() );
BOOST_CHECK_EQUAL(deckStringItem.size(), 0);
deckStringItem.push_backDummyDefault();
@@ -43,14 +43,14 @@ BOOST_AUTO_TEST_CASE(DummyDefaults) {
}
BOOST_AUTO_TEST_CASE(GetStringAtIndex_NoData_ExceptionThrown) {
auto deckStringItem = DeckItem::make< std::string >("TEST");
DeckItem deckStringItem( "TEST", std::string() );
BOOST_CHECK_THROW(deckStringItem.get< std::string >(0), std::out_of_range);
deckStringItem.push_back("SA");
BOOST_CHECK_THROW(deckStringItem.get< std::string >(1), std::out_of_range);
}
BOOST_AUTO_TEST_CASE(size_variouspushes_sizecorrect) {
auto deckStringItem = DeckItem::make< std::string >("TEST");
DeckItem deckStringItem( "TEST", std::string() );
BOOST_CHECK_EQUAL(0U, deckStringItem.size());
deckStringItem.push_back("WELL-3");
@@ -62,7 +62,7 @@ BOOST_AUTO_TEST_CASE(size_variouspushes_sizecorrect) {
}
BOOST_AUTO_TEST_CASE(DefaultNotApplied) {
auto deckStringItem = DeckItem::make< std::string >("TEST");
DeckItem deckStringItem( "TEST", std::string() );
BOOST_CHECK( deckStringItem.size() == 0 );
deckStringItem.push_back( "FOO") ;
@@ -72,7 +72,7 @@ BOOST_AUTO_TEST_CASE(DefaultNotApplied) {
}
BOOST_AUTO_TEST_CASE(DefaultApplied) {
auto deckStringItem = DeckItem::make< std::string >("TEST");
DeckItem deckStringItem( "TEST", std::string() );
BOOST_CHECK( deckStringItem.size() == 0 );
deckStringItem.push_backDefault( "FOO" );
@@ -83,7 +83,7 @@ BOOST_AUTO_TEST_CASE(DefaultApplied) {
BOOST_AUTO_TEST_CASE(PushBackMultiple) {
auto stringItem = DeckItem::make< std::string >("HEI");
DeckItem stringItem( "TEST", std::string() );
stringItem.push_back("Heisann ", 100U );
BOOST_CHECK_EQUAL( 100U , stringItem.size() );
for (size_t i=0; i < 100; i++)

View File

@@ -249,9 +249,9 @@ static Deck deckWithGRUPTREE() {
DeckKeyword gruptreeKeyword("GRUPTREE");
DeckRecord recordChildOfField;
auto itemChild1 = DeckItem::make< std::string >( "CHILD_GROUP" );
DeckItem itemChild1( "CHILD_GROUP", std::string() );
itemChild1.push_back(std::string("BARNET"));
auto itemParent1 = DeckItem::make< std::string >( "PARENT_GROUP" );
DeckItem itemParent1( "PARENT_GROUP", std::string() );
itemParent1.push_back(std::string("FAREN"));
recordChildOfField.addItem( std::move( itemChild1 ) );

View File

@@ -103,11 +103,11 @@ BOOST_AUTO_TEST_CASE(AddStepSizeCorrect) {
BOOST_AUTO_TEST_CASE( dateFromEclipseThrowsInvalidRecord ) {
Opm::DeckRecord startRecord;
auto dayItem = Opm::DeckItem::make< int >("DAY");
auto monthItem = Opm::DeckItem::make< std::string >("MONTH");
auto yearItem = Opm::DeckItem::make< int >("YEAR");
auto timeItem = Opm::DeckItem::make< std::string >("TIME");
auto extraItem = Opm::DeckItem::make< int >("EXTRA");
Opm::DeckItem dayItem("DAY", int() );
Opm::DeckItem monthItem("MONTH", std::string() );
Opm::DeckItem yearItem("YEAR", int() );
Opm::DeckItem timeItem("TIME", std::string() );
Opm::DeckItem extraItem("EXTRA", int() );
dayItem.push_back( 10 );
yearItem.push_back(1987 );
@@ -116,19 +116,19 @@ BOOST_AUTO_TEST_CASE( dateFromEclipseThrowsInvalidRecord ) {
BOOST_CHECK_THROW( Opm::TimeMap::timeFromEclipse( startRecord ) , std::invalid_argument );
startRecord.addItem( std::move( dayItem ) );
startRecord.addItem( dayItem );
BOOST_CHECK_THROW( Opm::TimeMap::timeFromEclipse( startRecord ) , std::invalid_argument );
startRecord.addItem( std::move( monthItem ) );
startRecord.addItem( monthItem );
BOOST_CHECK_THROW( Opm::TimeMap::timeFromEclipse( startRecord ) , std::invalid_argument );
startRecord.addItem( std::move( yearItem ) );
startRecord.addItem( yearItem );
BOOST_CHECK_THROW(Opm::TimeMap::timeFromEclipse( startRecord ) , std::invalid_argument );
startRecord.addItem( std::move( timeItem ) );
startRecord.addItem( timeItem );
BOOST_CHECK_NO_THROW(Opm::TimeMap::timeFromEclipse( startRecord ));
startRecord.addItem( std::move( extraItem ) );
startRecord.addItem( extraItem );
BOOST_CHECK_THROW( Opm::TimeMap::timeFromEclipse( startRecord ) , std::invalid_argument );
}
@@ -136,17 +136,17 @@ BOOST_AUTO_TEST_CASE( dateFromEclipseThrowsInvalidRecord ) {
BOOST_AUTO_TEST_CASE( dateFromEclipseInvalidMonthThrows ) {
Opm::DeckRecord startRecord;
auto dayItem = Opm::DeckItem::make< int >("DAY");
auto monthItem = Opm::DeckItem::make< std::string >("MONTH");
auto yearItem = Opm::DeckItem::make< int >("YEAR");
Opm::DeckItem dayItem( "DAY", int() );
Opm::DeckItem monthItem( "MONTH", std::string() );
Opm::DeckItem yearItem( "YEAR", int() );
dayItem.push_back( 10 );
yearItem.push_back(1987 );
monthItem.push_back("XXX");
startRecord.addItem( std::move( dayItem ) );
startRecord.addItem( std::move( monthItem ) );
startRecord.addItem( std::move( yearItem ) );
startRecord.addItem( dayItem );
startRecord.addItem( monthItem );
startRecord.addItem( yearItem );
BOOST_CHECK_THROW( Opm::TimeMap::timeFromEclipse( startRecord ) , std::invalid_argument );
}
@@ -177,10 +177,10 @@ BOOST_AUTO_TEST_CASE( timeFromEclipseCheckMonthNames ) {
BOOST_AUTO_TEST_CASE( timeFromEclipseInputRecord ) {
Opm::DeckRecord startRecord;
auto dayItem = Opm::DeckItem::make< int >("DAY");
auto monthItem = Opm::DeckItem::make< std::string >("MONTH");
auto yearItem = Opm::DeckItem::make< int >("YEAR");
auto timeItem = Opm::DeckItem::make< std::string >("TIME");
Opm::DeckItem dayItem( "DAY", int() );
Opm::DeckItem monthItem( "MONTH", std::string() );
Opm::DeckItem yearItem("YEAR", int() );
Opm::DeckItem timeItem("TIME", std::string() );
dayItem.push_back( 10 );
yearItem.push_back( 1987 );

View File

@@ -1,70 +0,0 @@
/*
Copyright 2014 Statoil ASA.
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OPM_RECORD_VECTOR_HPP
#define OPM_RECORD_VECTOR_HPP
#include <vector>
#include <stdexcept>
/*
A vector like container which will return the last valid element
when the lookup index is out of range.
*/
namespace Opm {
template <typename T>
class RecordVector {
private:
std::vector<T> m_data;
public:
size_t size() const {
return m_data.size();
}
T get(size_t index) const {
if (m_data.size() > 0) {
if (index >= m_data.size())
return m_data.back();
else
return m_data[index];
} else
throw std::invalid_argument("Trying to get from empty RecordVector");
}
void push_back(T value) {
m_data.push_back(value);
}
typename std::vector<T>::const_iterator begin() const {
return m_data.begin();
}
typename std::vector<T>::const_iterator end() const {
return m_data.end();
}
};
}
#endif

View File

@@ -1,4 +1,4 @@
foreach(tapp OrderedMapTests ValueTests RecordVectorTests)
foreach(tapp OrderedMapTests ValueTests)
opm_add_test(run${tapp} SOURCES ${tapp}.cpp
LIBRARIES opmparser ${Boost_LIBRARIES})
endforeach()

View File

@@ -1,49 +0,0 @@
/*
Copyright 2014 Statoil ASA.
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdexcept>
#include <iostream>
#include <boost/filesystem.hpp>
#define BOOST_TEST_MODULE ScheduleTests
#include <boost/test/unit_test.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <opm/parser/eclipse/EclipseState/Util/RecordVector.hpp>
BOOST_AUTO_TEST_CASE( check_empty) {
Opm::RecordVector<int> vector;
BOOST_CHECK_EQUAL( 0U , vector.size());
BOOST_CHECK_THROW( vector.get(0) , std::invalid_argument );
}
BOOST_AUTO_TEST_CASE( check_add ) {
Opm::RecordVector<int> vector;
vector.push_back(10);
BOOST_CHECK_EQUAL( 1U , vector.size());
BOOST_CHECK_EQUAL( 10 , vector.get(0));
BOOST_CHECK_EQUAL( 10 , vector.get(10));
vector.push_back(20);
BOOST_CHECK_EQUAL( 2U , vector.size());
BOOST_CHECK_EQUAL( 10 , vector.get(0));
BOOST_CHECK_EQUAL( 20 , vector.get(1));
BOOST_CHECK_EQUAL( 20 , vector.get(10));
}

View File

@@ -143,7 +143,7 @@ namespace Opm {
/// NOTE: data are popped from the rawRecords deque!
template<typename ParserItemType, typename ValueType>
DeckItem ParserItemScan(const ParserItemType * self, RawRecord& rawRecord ) {
auto deckItem = DeckItem::make< ValueType >( self->name(), rawRecord.size() );
DeckItem deckItem( self->name(), ValueType(), rawRecord.size() );
if (self->sizeType() == ALL) {
while (rawRecord.size() > 0) {

View File

@@ -20,7 +20,7 @@ extern "C" {
*/
int deck_item_get_type( const Opm::DeckItem * item ) {
return item->getType();
return static_cast< int >( item->getType() );
}
int deck_item_iget_int( const Opm::DeckItem * item , int index) {