Add insert ordered set

This commit is contained in:
Joakim Hove 2019-07-24 08:38:39 +02:00
parent 28e0b1cc3a
commit f386404408
3 changed files with 167 additions and 0 deletions

View File

@ -422,6 +422,7 @@ if(ENABLE_ECL_INPUT)
opm/parser/eclipse/EclipseState/InitConfig/Equil.hpp
opm/parser/eclipse/EclipseState/InitConfig/FoamConfig.hpp
opm/parser/eclipse/EclipseState/Util/Value.hpp
opm/parser/eclipse/EclipseState/Util/IOrderSet.hpp
opm/parser/eclipse/EclipseState/Util/OrderedMap.hpp
opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp
opm/parser/eclipse/EclipseState/Edit/EDITNNC.hpp

View File

@ -0,0 +1,114 @@
/*
Copyright 2019 Equinor 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_IORDER_SET_HPP
#define OPM_IORDER_SET_HPP
#include <algorithm>
#include <iterator>
#include <stdexcept>
#include <string>
#include <unordered_set>
#include <list>
namespace Opm {
/*
Small class which implements a container which behaves roughly like
std::set<T>, but the insert order is preserved - i.e. when iterating over the
elements in the container they will come out in the order they have been
inserted. If an element is added multiple times the order in the container
will not be updated.
The set has an erase() method which can be used to remove elements, otherwise
the elements in the container are immutable.
The elements are duplicated in the std::set<T> and std::vector<T>, and the
class should not be used for large objects.
*/
template <typename T>
class IOrderSet {
using storage_type = typename std::vector<T>;
using index_type = typename std::unordered_set<T>;
using const_iter_type = typename storage_type::const_iterator;
private:
index_type index;
storage_type m_data;
public:
std::size_t size() const {
return this->index.size();
}
bool empty() const {
return (this->size() == 0);
}
std::size_t count(const T& value) const {
return this->index.count(value);
}
bool contains(const T& value) const {
return (this->count(value) != 0);
}
bool insert(const T& value) {
if (this->contains(value))
return false;
this->index.insert(value);
this->m_data.push_back(value);
return true;
}
std::size_t erase(const T& value) {
if (!this->contains(value))
return 0;
this->index.erase(value);
auto data_iter = std::find(this->m_data.begin(), this->m_data.end(), value);
this->m_data.erase(data_iter);
return 1;
}
const_iter_type begin() const {
return this->m_data.begin();
}
const_iter_type end() const {
return this->m_data.end();
}
const T& operator[](std::size_t i) const {
return this->m_data.at(i);
}
const std::vector<T>& data() const {
return this->m_data;
};
};
}
#endif

View File

@ -26,6 +26,7 @@
#include <boost/date_time/posix_time/posix_time.hpp>
#include <opm/parser/eclipse/EclipseState/Util/OrderedMap.hpp>
#include <opm/parser/eclipse/EclipseState/Util/IOrderSet.hpp>
BOOST_AUTO_TEST_CASE( check_empty) {
@ -115,4 +116,55 @@ BOOST_AUTO_TEST_CASE( check_order ) {
*/
}
BOOST_AUTO_TEST_CASE(test_IOrderSet) {
Opm::IOrderSet<std::string> iset;
BOOST_CHECK(iset.empty());
BOOST_CHECK_EQUAL(iset.size(), 0);
BOOST_CHECK_EQUAL(iset.count("HEI"), 0);
BOOST_CHECK_EQUAL(iset.contains("HEI"), false);
BOOST_CHECK(iset.insert("HEI"));
BOOST_CHECK_EQUAL(iset.size(), 1);
BOOST_CHECK_EQUAL(iset.count("HEI"), 1);
BOOST_CHECK_EQUAL(iset.contains("HEI"), true);
BOOST_CHECK(!iset.insert("HEI"));
BOOST_CHECK_EQUAL(iset.size(), 1);
BOOST_CHECK_EQUAL(iset.count("HEI"), 1);
BOOST_CHECK_EQUAL(iset.contains("HEI"), true);
BOOST_CHECK_THROW(iset[10], std::out_of_range);
Opm::IOrderSet<int> iset2;
for (int i=10; i >= 0; i--)
iset2.insert(i);
int expected = 10;
std::size_t index=0;
const auto &d = iset2.data();
for (const auto &v : iset2) {
BOOST_CHECK_EQUAL(v, expected);
BOOST_CHECK_EQUAL(iset2[index], expected);
BOOST_CHECK_EQUAL(d[index], expected);
expected--;
index++;
}
Opm::IOrderSet<std::string> iset3;
iset3.insert("AAA");
iset3.insert("BBB");
BOOST_CHECK_EQUAL(iset3[0], "AAA");
BOOST_CHECK_EQUAL(iset3[1], "BBB");
BOOST_CHECK_EQUAL(iset3.erase("AAA"), 1);
BOOST_CHECK_EQUAL(iset3.size() , 1);
BOOST_CHECK_EQUAL(iset3[0], "BBB");
BOOST_CHECK_EQUAL(iset3.erase("AAA"), 0);
BOOST_CHECK_EQUAL(iset3.size() , 1);
BOOST_CHECK_EQUAL(iset3[0], "BBB");
}