Files
opm-common/opm/parser/eclipse/Parser/ParserRecord.cpp
Jørgen Kvalsvik a22196546a ParserItem no longer requires heap alloc
Redesign of ParserItem so that its sum type nature no longer mandates
indirection, but rather a tag check on all operations. Because of this,
ParserRecords can now store ParserItems directly, and iterators are no
longer iterators to pointers, but behave like normal vector iterators.
2016-11-07 12:24:38 +01:00

188 lines
6.0 KiB
C++

/*
Copyright 2013 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 <opm/parser/eclipse/Deck/Deck.hpp>
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
#include <opm/parser/eclipse/Parser/ParserRecord.hpp>
#include <opm/parser/eclipse/Parser/ParserItem.hpp>
#include <opm/parser/eclipse/Parser/MessageContainer.hpp>
#include <opm/parser/eclipse/RawDeck/RawRecord.hpp>
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
namespace Opm {
namespace {
struct name_eq {
name_eq( const std::string& x ) : name( x ) {}
const std::string& name;
bool operator()( const ParserItem& x ) const {
return x.name() == this->name;
}
};
}
ParserRecord::ParserRecord()
: m_dataRecord( false )
{
}
size_t ParserRecord::size() const {
return m_items.size();
}
void ParserRecord::addItem( ParserItem item ) {
if (m_dataRecord)
throw std::invalid_argument("Record is already marked as DataRecord - can not add items");
auto itr = std::find_if( this->m_items.begin(),
this->m_items.end(),
name_eq( item.name() ) );
if( itr != this->m_items.end() )
throw std::invalid_argument("Itemname: " + item.name() + " already exists.");
this->m_items.push_back( std::move( item ) );
}
void ParserRecord::addDataItem( ParserItem item ) {
if (m_items.size() > 0)
throw std::invalid_argument("Record already contains items - can not add Data Item");
this->addItem( std::move( item) );
m_dataRecord = true;
}
std::vector< ParserItem >::const_iterator ParserRecord::begin() const {
return m_items.begin();
}
std::vector< ParserItem >::const_iterator ParserRecord::end() const {
return m_items.end();
}
bool ParserRecord::hasDimension() const {
return std::any_of( this->begin(), this->end(),
[]( const ParserItem& x ) { return x.hasDimension(); } );
}
void ParserRecord::applyUnitsToDeck( Deck& deck, DeckRecord& deckRecord ) const {
for( const auto& item : *this ) {
if( !item.hasDimension() ) continue;
auto& deckItem = deckRecord.getItem( item.name() );
for (size_t idim = 0; idim < item.numDimensions(); idim++) {
auto activeDimension = deck.getActiveUnitSystem().getNewDimension( item.getDimension(idim) );
auto defaultDimension = deck.getDefaultUnitSystem().getNewDimension( item.getDimension(idim) );
deckItem.push_backDimension( activeDimension , defaultDimension );
}
}
}
const ParserItem& ParserRecord::get(size_t index) const {
return this->m_items.at( index );
}
bool ParserRecord::hasItem( const std::string& name ) const {
return std::any_of( this->m_items.begin(),
this->m_items.end(),
name_eq( name ) );
}
const ParserItem& ParserRecord::get( const std::string& name ) const {
auto itr = std::find_if( this->m_items.begin(),
this->m_items.end(),
name_eq( name ) );
if( itr == this->m_items.end() )
throw std::out_of_range( "No item '" + name + "'" );
return *itr;
}
DeckRecord ParserRecord::parse(const ParseContext& parseContext , MessageContainer& msgContainer, RawRecord& rawRecord ) const {
std::vector< DeckItem > items;
items.reserve( this->size() + 20 );
for( const auto& parserItem : *this )
items.emplace_back( parserItem.scan( rawRecord ) );
if (rawRecord.size() > 0) {
std::string msg = "The RawRecord for keyword \"" + rawRecord.getKeywordName() + "\" in file\"" + rawRecord.getFileName() + "\" contained " +
std::to_string(rawRecord.size()) +
" too many items according to the spec. RawRecord was: " + rawRecord.getRecordString();
parseContext.handleError(ParseContext::PARSE_EXTRA_DATA , msgContainer, msg);
}
return { std::move( items ) };
}
bool ParserRecord::equal(const ParserRecord& other) const {
bool equal_ = true;
if (size() == other.size()) {
size_t itemIndex = 0;
while (true) {
if (itemIndex == size())
break;
{
const auto& item = get(itemIndex);
const auto& otherItem = other.get(itemIndex);
if (item != otherItem ) {
equal_ = false;
break;
}
}
itemIndex++;
}
} else
equal_ = false;
return equal_;
}
bool ParserRecord::isDataRecord() const {
return m_dataRecord;
}
bool ParserRecord::operator==( const ParserRecord& rhs ) const {
return this->equal( rhs );
}
bool ParserRecord::operator!=( const ParserRecord& rhs ) const {
return !( *this == rhs );
}
std::ostream& operator<<( std::ostream& stream, const ParserRecord& rec ) {
stream << " ParserRecord { " << std::endl;
for( const auto& item : rec )
stream << " " << item << std::endl;
return stream << " }";
}
}