Files
opm-common/opm/parser/eclipse/EclipseState/Schedule/GroupTree.cpp
Jørgen Kvalsvik bfa108deef Replace explicit GroupTree with ordered strings
Replaces The GroupTree + GroupTreeNode classes building an explicit tree
of named nodes with a sorted vector of { name, parent-name } pairs that
builds an implicit tree. Provides the same semantics as the previous
group tree implementation, but with less code and copying for free.
2016-11-11 13:21:20 +01:00

135 lines
4.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 <algorithm>
#include <stdexcept>
#include <opm/parser/eclipse/EclipseState/Schedule/GroupTree.hpp>
namespace Opm {
void GroupTree::update( const std::string& name ) {
this->update( name, "FIELD" );
}
/*
* Insertions are only done via the update method which maintains the
* underlying group vector sorted on group names. This requires group names to
* be unique, but simplifies the implementation greatly and emphasises that
* this grouptree class is just meta data for the actual group objects (stored
* and represented elsewhere)
*/
void GroupTree::update( const std::string& name, const std::string& parent ) {
if( name == "FIELD" )
throw std::invalid_argument( "The FIELD group name is reserved." );
if( parent.empty() )
throw std::invalid_argument( "Parent group must have a name." );
auto root = this->find( parent );
if( root == this->groups.end() || root->name != parent )
this->groups.insert( root, 1, group { parent, "FIELD" } );
auto node = this->find( name );
if( node == this->groups.end() || node->name != name ) {
this->groups.insert( node, 1, group { name, parent } );
return;
}
node->parent = parent;
}
bool GroupTree::exists( const std::string& name ) const {
return std::binary_search( this->groups.begin(),
this->groups.end(),
name );
}
const std::string& GroupTree::parent( const std::string& name ) const {
auto node = std::find( this->groups.begin(), this->groups.end(), name );
if( node == this->groups.end() )
throw std::out_of_range( "No such parent '" + name + "'." );
return node->parent;
}
std::vector< std::string > GroupTree::children( const std::string& parent ) const {
if( !this->exists( parent ) )
throw std::out_of_range( "Node '" + parent + "' does not exist." );
std::vector< std::string > kids;
for( const auto& node : this->groups ) {
if( node.parent != parent ) continue;
kids.push_back( node.name );
}
return kids;
}
bool GroupTree::operator==( const GroupTree& rhs ) const {
return this->groups.size() == rhs.groups.size()
&& std::equal( this->groups.begin(),
this->groups.end(),
rhs.groups.begin() );
}
bool GroupTree::operator!=( const GroupTree& rhs ) const {
return !( *this == rhs );
}
bool GroupTree::group::operator==( const std::string& rhs ) const {
return this->name == rhs;
}
bool GroupTree::group::operator!=( const std::string& rhs ) const {
return !( *this == rhs );
}
bool GroupTree::group::operator==( const GroupTree::group& rhs ) const {
return this->name == rhs.name && this->parent == rhs.parent;
}
bool GroupTree::group::operator!=( const GroupTree::group& rhs ) const {
return !( *this == rhs );
}
bool GroupTree::group::operator<( const GroupTree::group& rhs ) const {
return this->name < rhs.name;
}
bool GroupTree::group::operator<( const std::string& rhs ) const {
return this->name < rhs;
}
bool operator<( const std::string& lhs, const GroupTree::group& rhs ) {
return lhs < rhs.name;
}
std::vector< GroupTree::group >::iterator GroupTree::find( const std::string& name ) {
return std::lower_bound( this->groups.begin(),
this->groups.end(),
name );
}
}