Use value::status to keep track of data status in DeckItem

With this commit the DeckItem::push_backDummyDefault() function will push back a
default value T( ). This will give a change in behaviour in downstream code
which has used getData<T> to get DeckItem data unchecked.
This commit is contained in:
Joakim Hove 2019-11-17 14:46:00 +01:00
parent 3156448f99
commit 6cc3b578f5
8 changed files with 64 additions and 54 deletions

View File

@ -28,12 +28,15 @@
#include <opm/parser/eclipse/Units/Dimension.hpp>
#include <opm/parser/eclipse/Utility/Typetools.hpp>
#include <opm/parser/eclipse/Deck/UDAValue.hpp>
#include <opm/parser/eclipse/Deck/value_status.hpp>
namespace Opm {
class DeckOutput;
class DeckItem {
public:
DeckItem() = default;
DeckItem( const std::string&, int);
DeckItem( const std::string&, std::string);
@ -59,7 +62,6 @@ namespace Opm {
// keyword, though...
size_t data_size() const;
size_t out_size() const;
template<typename T>
T get( size_t index ) const;
@ -84,6 +86,8 @@ namespace Opm {
void push_backDefault( double );
void push_backDefault( std::string );
// trying to access the data of a "dummy default item" will raise an exception
template <typename T>
void push_backDummyDefault();
type_tag getType() const;
@ -120,7 +124,7 @@ namespace Opm {
type_tag type = type_tag::unknown;
std::string item_name;
std::vector< bool > defaulted;
std::vector<value::status> value_status;
/*
To save space we mutate the dval object in place when asking for SI
data; the current state of of the dval member is tracked with the

View File

@ -105,39 +105,30 @@ const std::string& DeckItem::name() const {
}
bool DeckItem::defaultApplied( size_t index ) const {
return this->defaulted.at( index );
return value::defaulted( this->value_status.at(index));
}
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;
case type_tag::uda: return this->uval.size() > index;
default: throw std::logic_error( "DeckItem::hasValue: Type not set." );
}
if (index >= this->value_status.size())
return false;
return value::has_value( this->value_status[index] );
}
size_t DeckItem::data_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();
case type_tag::uda: return this->uval.size();
default: throw std::logic_error( "DeckItem::size: Type not set." );
}
}
size_t DeckItem::out_size() const {
size_t data_size = this->data_size();
return std::max( data_size , this->defaulted.size() );
return this->value_status.size();
}
template< typename T >
T DeckItem::get( size_t index ) const {
return this->value_ref< T >().at( index );
if (index >= this->value_status.size())
throw std::out_of_range("Invalid index");
if (!value::has_value(this->value_status[index]))
throw std::invalid_argument("Invalid arguemnt");
return this->value_ref< T >()[index];
}
template<>
@ -147,7 +138,7 @@ UDAValue DeckItem::get( size_t index ) const {
return value;
std::size_t dim_index = index % this->active_dimensions.size();
if (this->defaulted[index])
if (value::defaulted(this->value_status[index]))
return UDAValue( value, this->default_dimensions[dim_index]);
else
return UDAValue( value, this->active_dimensions[dim_index]);
@ -165,7 +156,7 @@ void DeckItem::push( T x ) {
auto& val = this->value_ref< T >();
val.push_back( std::move( x ) );
this->defaulted.push_back( false );
this->value_status.push_back( value::status::deck_value );
}
void DeckItem::push_back( int x ) {
@ -189,7 +180,7 @@ 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 );
this->value_status.insert( this->value_status.end(), n, value::status::deck_value );
}
void DeckItem::push_back( int x, size_t n ) {
@ -211,12 +202,12 @@ void DeckItem::push_back( UDAValue x, size_t n ) {
template< typename T >
void DeckItem::push_default( T x ) {
auto& val = this->value_ref< T >();
if( this->defaulted.size() != val.size() )
if( this->value_status.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 );
this->value_status.push_back( value::status::valid_default );
}
void DeckItem::push_backDefault( int x ) {
@ -236,11 +227,11 @@ void DeckItem::push_backDefault( UDAValue x ) {
}
template<typename T>
void DeckItem::push_backDummyDefault() {
if( !this->defaulted.empty() )
throw std::logic_error("Pseudo defaults can only be specified for empty items");
this->defaulted.push_back( true );
auto& val = this->value_ref< T >();
val.push_back( T() );
this->value_status.push_back( value::status::empty_default );
}
std::string DeckItem::getTrimmedString( size_t index ) const {
@ -262,8 +253,13 @@ const std::vector<double>& DeckItem::getData() const {
const auto dim_size = this->active_dimensions.size();
for( size_t index = 0; index < data.size(); index++ ) {
const auto dimIndex = index % dim_size;
const auto& dim = this->defaulted[index] ? this->default_dimensions[dimIndex] : this->active_dimensions[dimIndex];
data[ index ] = dim.convertSiToRaw( data[ index ] );
if (value::defaulted(this->value_status[index])) {
const auto& dim = this->default_dimensions[dimIndex];
data[ index ] = dim.convertSiToRaw( data[ index ] );
} else {
const auto& dim = this->active_dimensions[dimIndex];
data[ index ] = dim.convertSiToRaw( data[ index ] );
}
}
this->raw_data = true;
return data;
@ -289,8 +285,13 @@ const std::vector< double >& DeckItem::getSIDoubleData() const {
const auto sz = data.size();
for( size_t index = 0; index < sz; index++ ) {
const auto dimIndex = index % dim_size;
const auto& dim = this->defaulted[index] ? this->default_dimensions[dimIndex] : this->active_dimensions[dimIndex];
data[ index ] = dim.convertRawToSi( data[ index ] );
if (value::defaulted(this->value_status[index])) {
const auto& dim = this->default_dimensions[dimIndex];
data[ index ] = dim.convertRawToSi( data[ index ] );
} else {
const auto& dim = this->active_dimensions[dimIndex];
data[ index ] = dim.convertRawToSi( data[ index ] );
}
}
this->raw_data = false;
return data;
@ -305,7 +306,7 @@ type_tag DeckItem::getType() const {
template< typename T >
void DeckItem::write_vector(DeckOutput& stream, const std::vector<T>& data) const {
for (size_t index = 0; index < this->out_size(); index++) {
for (size_t index = 0; index < this->data_size(); index++) {
if (this->defaultApplied(index))
stream.stash_default( );
else
@ -373,7 +374,7 @@ bool DeckItem::equal(const DeckItem& other, bool cmp_default, bool cmp_numeric)
return false;
if (cmp_default)
if (this->defaulted != other.defaulted)
if (this->value_status != other.value_status)
return false;
switch( this->type ) {
@ -469,6 +470,11 @@ template double DeckItem::get< double >( size_t ) const;
template std::string DeckItem::get< std::string >( size_t ) const;
template UDAValue DeckItem::get< UDAValue >( size_t ) const;
template void DeckItem::push_backDummyDefault<int>();
template void DeckItem::push_backDummyDefault<double>();
template void DeckItem::push_backDummyDefault<std::string>();
template void DeckItem::push_backDummyDefault<UDAValue>();
template const std::vector< int >& DeckItem::getData< int >() const;
template const std::vector< UDAValue >& DeckItem::getData< UDAValue >() const;
template const std::vector< std::string >& DeckItem::getData< std::string >() const;

View File

@ -55,7 +55,7 @@ namespace Opm {
if (parser_item.hasDefault())
deck_item.push_back( parser_item.getDefault<T>() );
else
deck_item.push_backDummyDefault();
deck_item.push_backDummyDefault<T>();
}
else if (input_record[j].is_compatible<T>())
deck_item.push_back( input_record[j].get<T>() );

View File

@ -513,7 +513,7 @@ void scan_item( DeckItem& deck_item, const ParserItem& parser_item, RawRecord& r
} else {
// ... otherwise indicate that the deck item should throw once the
// item's data is accessed.
deck_item.push_backDummyDefault();
deck_item.push_backDummyDefault<T>();
}
return;
@ -541,7 +541,7 @@ void scan_item( DeckItem& deck_item, const ParserItem& parser_item, RawRecord& r
else if( parser_item.hasDefault() )
deck_item.push_backDefault( parser_item.getDefault< T >() );
else
deck_item.push_backDummyDefault();
deck_item.push_backDummyDefault<T>();
const auto value_start = token.size() - valueString.size();
// replace the first occurence of "N*FOO" by a sequence of N-1 times

View File

@ -166,10 +166,10 @@ BOOST_AUTO_TEST_CASE(DummyDefaultsString) {
DeckItem deckStringItem("TEST", std::string() );
BOOST_CHECK_EQUAL(deckStringItem.data_size(), 0);
deckStringItem.push_backDummyDefault();
BOOST_CHECK_EQUAL(deckStringItem.data_size(), 0);
deckStringItem.push_backDummyDefault<std::string>();
BOOST_CHECK_EQUAL(deckStringItem.data_size(), 1);
BOOST_CHECK_EQUAL(true, deckStringItem.defaultApplied(0));
BOOST_CHECK_THROW(deckStringItem.get< std::string >(0), std::out_of_range);
BOOST_CHECK_THROW(deckStringItem.get< std::string >(0), std::invalid_argument);
}
BOOST_AUTO_TEST_CASE(GetStringAtIndex_NoData_ExceptionThrown) {
@ -270,10 +270,10 @@ BOOST_AUTO_TEST_CASE(DummyDefaultsDouble) {
DeckItem deckDoubleItem( "TEST", double(), dims.first, dims.second);
BOOST_CHECK_EQUAL(deckDoubleItem.data_size(), 0);
deckDoubleItem.push_backDummyDefault();
BOOST_CHECK_EQUAL(deckDoubleItem.data_size(), 0);
deckDoubleItem.push_backDummyDefault<double>();
BOOST_CHECK_EQUAL(deckDoubleItem.data_size(), 1);
BOOST_CHECK_EQUAL(true, deckDoubleItem.defaultApplied(0));
BOOST_CHECK_THROW(deckDoubleItem.get< double >(0), std::out_of_range);
BOOST_CHECK_THROW(deckDoubleItem.get< double >(0), std::invalid_argument);
}
BOOST_AUTO_TEST_CASE(PushBackMultipleDouble) {
@ -344,12 +344,12 @@ BOOST_AUTO_TEST_CASE(DummyDefaultsInt) {
DeckItem deckIntItem( "TEST", int() );
BOOST_CHECK_EQUAL(deckIntItem.data_size(), 0);
deckIntItem.push_backDummyDefault();
BOOST_CHECK_EQUAL(deckIntItem.data_size(), 0);
deckIntItem.push_backDummyDefault<int>();
BOOST_CHECK_EQUAL(deckIntItem.data_size(), 1);
BOOST_CHECK_EQUAL(true, deckIntItem.defaultApplied(0));
BOOST_CHECK_EQUAL( false , deckIntItem.hasValue(0));
BOOST_CHECK_EQUAL( false , deckIntItem.hasValue(1));
BOOST_CHECK_THROW(deckIntItem.get< int >(0), std::out_of_range);
BOOST_CHECK_THROW(deckIntItem.get< int >(0), std::invalid_argument);
}
BOOST_AUTO_TEST_CASE(GetIntAtIndex_NoData_ExceptionThrown) {

View File

@ -1247,7 +1247,7 @@ BOOST_AUTO_TEST_CASE(Parse_RawRecordTooFewItems) {
BOOST_CHECK_NO_THROW(parserRecord.parse(parseContext, errors, rawRecord, unit_system, unit_system, "KEWYORD", "filename"));
auto record = parserRecord.parse(parseContext, errors , rawRecord, unit_system, unit_system, "KEYWORD", "filename");
BOOST_CHECK_NO_THROW(record.getItem(2));
BOOST_CHECK_THROW(record.getItem(2).get< int >(0), std::out_of_range);
BOOST_CHECK_THROW(record.getItem(2).get< int >(0), std::invalid_argument);
}

View File

@ -1099,7 +1099,7 @@ BOOST_AUTO_TEST_CASE(createDeckWithWeltArgException2) {
TableManager table ( deck );
Eclipse3DProperties eclipseProperties ( deck , table, grid);
Runspec runspec (deck);
BOOST_CHECK_THROW(Schedule(deck, grid , eclipseProperties, runspec), std::out_of_range);
BOOST_CHECK_THROW(Schedule(deck, grid , eclipseProperties, runspec), std::invalid_argument);
}
BOOST_AUTO_TEST_CASE(createDeckWithWPIMULT) {

View File

@ -1012,7 +1012,7 @@ VFPPROD \n\
auto units = Opm::UnitSystem::newMETRIC();
BOOST_CHECK_EQUAL(deck.count("VFPPROD"), 1);
BOOST_CHECK_THROW(Opm::VFPProdTable(vfpprodKeyword, units), std::out_of_range);
BOOST_CHECK_THROW(Opm::VFPProdTable(vfpprodKeyword, units), std::invalid_argument);
}