My Project
Loading...
Searching...
No Matches
OrderedMap.hpp
1/*
2 Copyright 2014 Statoil ASA.
3
4 This file is part of the Open Porous Media project (OPM).
5
6 OPM is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 OPM is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with OPM. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#ifndef OPM_ORDERED_MAP_HPP
21#define OPM_ORDERED_MAP_HPP
22
23#include <algorithm>
24#include <cctype>
25#include <cstddef>
26#include <functional>
27#include <iterator>
28#include <set>
29#include <stdexcept>
30#include <string>
31#include <string_view>
32#include <tuple>
33#include <unordered_map>
34#include <utility>
35#include <vector>
36
37namespace Opm {
38
39namespace OrderedMapDetail
40{
41
42template<class T, class A>
43std::string
44findSimilarStrings(std::string str,
45 const std::vector<std::pair<std::string, T>,A>& storage)
46{
47 auto toUpper = [](const char c){ return std::toupper(c);};
48 std::transform(str.begin(), str.end(), str.begin(), toUpper);
49 std::set<std::string> alternatives;
50
51 for(const auto& entry: storage)
52 {
53 std::string upper = entry.first;
54 std::transform(upper.begin(), upper.end(), upper.begin(),
55 toUpper);
56
57 if(upper.find(str) != std::string::npos || str.find(upper) != std::string::npos)
58 {
59 alternatives.insert(entry.first);
60 }
61 }
62
63 if (alternatives.empty())
64 {
65 return {};
66 }
67
68 std::string concatedStr;
69 for (const auto& alt : alternatives) {
70 concatedStr += alt;
71 concatedStr += ", ";
72 }
73 return concatedStr.substr(0, concatedStr.size()-2);
74}
75
76template<std::string_view::size_type MAX_CHARS>
78{
79public:
80 std::size_t operator()(std::string_view key) const
81 {
82 return hasher(key.substr(0, MAX_CHARS));
83 }
84private:
85 std::hash<std::string_view> hasher;
86};
87
88
89template<>
90class TruncatedStringHash<std::string_view::npos> : public std::hash<std::string_view>
91{};
92
93template<std::string_view::size_type MAX_CHARS>
95{
96 bool operator()(std::string_view str1, std::string_view str2) const
97 {
98 return str1.substr(0, MAX_CHARS) == str2.substr(0, MAX_CHARS);
99 }
100};
101
102template<>
103struct TruncatedStringEquals<std::string::npos> : public std::equal_to<std::string>
104{};
105
106} // end namespace detail
107
120template <typename T, std::string_view::size_type MAX_CHARS = std::string_view::npos>
122public:
123 using storage_type = std::vector<std::pair<std::string, T>>;
124 using index_type = std::unordered_map<std::string, typename storage_type::size_type,
127 using iter_type = typename storage_type::iterator;
128 using const_iter_type = typename storage_type::const_iterator;
129
130private:
131 index_type m_map;
132 storage_type m_vector;
133
134public:
135
136 OrderedMap() = default;
137
138 OrderedMap(const index_type& index, const storage_type& storage)
139 : m_map(index)
140 , m_vector(storage)
141 {
142 }
143
144 const index_type& getIndex() const { return m_map; }
145
146 const storage_type& getStorage() const { return m_vector; }
147
148 std::size_t count(const std::string& key) const {
149 return this->m_map.count(key);
150 }
151
152
153
154 T& operator[](const std::string& key) {
155 if (this->count(key) == 0)
156 this->insert( std::make_pair(key, T()));
157
158 return this->at(key);
159 }
160
161
162 std::size_t erase(const std::string& key) {
163 if (this->count(key) == 0)
164 return 0;
165
166 std::size_t index = this->m_map.at(key);
167 this->m_map.erase(key);
168 this->m_vector.erase(this->m_vector.begin() + index);
169
170 for (const auto& index_pair : this->m_map) {
171 auto target_index = index_pair.second;
172 if (target_index > index)
173 target_index--;
174
175 this->m_map[index_pair.first] = target_index;
176 }
177 return 1;
178 }
179
180
181 void insert(std::pair<std::string,T> key_value_pair) {
182 if (this->count(key_value_pair.first) > 0) {
183 auto iter = m_map.find( key_value_pair.first );
184 size_t index = iter->second;
185 m_vector[index] = key_value_pair;
186 } else {
187 size_t index = m_vector.size();
188 this->m_map.emplace(key_value_pair.first, index);
189 this->m_vector.push_back( std::move( key_value_pair ) );
190 }
191 }
192
193
194 T& get(const std::string& key) {
195 auto iter = m_map.find( key );
196 if (iter == m_map.end())
197 {
198 using namespace std::string_literals;
199 auto startsWithSame = OrderedMapDetail::findSimilarStrings(key, m_vector);
200 if (!startsWithSame.empty())
201 {
202 startsWithSame = " Similar entries are "s +
203 startsWithSame + "."s;
204 }
205 throw std::invalid_argument("Key "s + key + " not found."s
206 + startsWithSame);
207 }
208 else {
209 size_t index = iter->second;
210 return iget(index);
211 }
212 }
213
214
215 T& iget(size_t index) {
216 if (index >= m_vector.size())
217 throw std::invalid_argument("Invalid index");
218 return m_vector[index].second;
219 }
220
221 const T& get(const std::string& key) const {
222 const auto& iter = this->m_map.find( key );
223 if (iter == m_map.end())
224 {
225 auto startsWithSame = OrderedMapDetail::findSimilarStrings(key, m_vector);
226 if (!startsWithSame.empty())
227 {
228 startsWithSame = std::string(" Similar entries are ") +
229 startsWithSame + std::string(".");
230 }
231 using namespace std::string_literals;
232 throw std::invalid_argument("Key "s + key + " not found."s
233 + startsWithSame);
234 }
235 else {
236 size_t index = iter->second;
237 return iget(index);
238 }
239 }
240
241
242 const T& iget(size_t index) const {
243 if (index >= m_vector.size())
244 {
245 using namespace std::string_literals;
246 throw std::invalid_argument("Invalid index "s +
247 std::to_string(index) +
248 " is larger than container size"s);
249 }
250 return m_vector[index].second;
251 }
252
253 const T& at(size_t index) const {
254 return this->iget(index);
255 }
256
257 const T& at(const std::string& key) const {
258 return this->get(key);
259 }
260
261 T& at(size_t index) {
262 return this->iget(index);
263 }
264
265 T& at(const std::string& key) {
266 return this->get(key);
267 }
268
269 size_t size() const {
270 return m_vector.size();
271 }
272
273
274 const_iter_type begin() const {
275 return m_vector.begin();
276 }
277
278
279 const_iter_type end() const {
280 return m_vector.end();
281 }
282
283 iter_type begin() {
284 return m_vector.begin();
285 }
286
287 iter_type end() {
288 return m_vector.end();
289 }
290
291 iter_type find(const std::string& key) {
292 const auto map_iter = this->m_map.find(key);
293 if (map_iter == this->m_map.end())
294 return this->m_vector.end();
295
296 return std::next(this->m_vector.begin(), map_iter->second);
297 }
298
299 const_iter_type find(const std::string& key) const {
300 const auto map_iter = this->m_map.find(key);
301 if (map_iter == this->m_map.end())
302 return this->m_vector.end();
303
304 return std::next(this->m_vector.begin(), map_iter->second);
305 }
306
307 template<size_t n>
308 bool operator==(const OrderedMap<T,n>& data) const {
309 return this->getIndex() == data.getIndex() &&
310 this->getStorage() == data.getStorage();
311 }
312
313 template<class Serializer>
314 void serializeOp(Serializer& serializer)
315 {
316 serializer(m_map);
317 serializer(m_vector);
318 }
319};
320}
321
322#endif
Definition OrderedMap.hpp:78
A map with iteration in the order of insertion.
Definition OrderedMap.hpp:121
Class for (de-)serializing.
Definition Serializer.hpp:84
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition Exceptions.hpp:30