My Project
Loading...
Searching...
No Matches
Serializer.hpp
1/*
2 This file is part of the Open Porous Media project (OPM).
3
4 OPM is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 2 of the License, or
7 (at your option) any later version.
8
9 OPM is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with OPM. If not, see <http://www.gnu.org/licenses/>.
16
17 Consult the COPYING file in the top-level source directory of this
18 module for the precise wording of the license and the list of
19 copyright holders.
20*/
21#ifndef SERIALIZER_HPP
22#define SERIALIZER_HPP
23
24#include <algorithm>
25#include <functional>
26#include <map>
27#include <memory>
28#include <optional>
29#include <set>
30#include <stdexcept>
31#include <type_traits>
32#include <utility>
33#include <unordered_map>
34#include <unordered_set>
35#include <variant>
36#include <vector>
37
38#if HAVE_DUNE_COMMON
39namespace Dune { template<typename,int> class FieldVector; }
40#endif
41
42#if HAVE_DUNE_ISTL
43namespace Dune { template<typename,typename> class BlockVector; }
44#endif
45
46namespace Opm {
47namespace detail {
48
49template<typename ...Ts>
51{
52
53template<std::size_t Index, typename, typename ...Rest>
54static decltype(auto) make_variant(std::size_t index)
55{
56 if(Index == index)
57 return std::variant<Ts...>{std::in_place_index_t<Index>{}};
58
59 if constexpr(sizeof...(Rest) != 0)
60 return make_variant<Index + 1, Rest...>(index);
61 else
62 throw std::runtime_error("Invalid variant index");
63}
64
65};
66
67template<typename ...Ts>
68decltype(auto) make_variant(std::size_t index)
69{
70 return detail::MakeVariantImpl<Ts...>::template make_variant<0, Ts...>(index);
71}
72
73template<class T>
74using remove_cvr_t = std::remove_cv_t<std::remove_reference_t<T>>;
75
76} // namespace detail
77
83template<class Packer>
85public:
88 explicit Serializer(const Packer& packer) :
90 {}
91
93 template<class T>
94 void operator()(const T& data)
95 {
96 if constexpr (is_ptr<T>::value) {
97 ptr(data);
98 } else if constexpr (is_pair_or_tuple<T>::value) {
99 tuple(data);
100 } else if constexpr (is_variant<T>::value) {
101 variant(data);
102 } else if constexpr (is_optional<T>::value) {
103 optional(data);
104 } else if constexpr (is_vector<T>::value) {
105 vector(data);
106 } else if constexpr (is_map<T>::value) {
107 map(data);
108 } else if constexpr (is_array<T>::value) {
109 array(data);
110 } else if constexpr (is_set<T>::value) {
111 set(data);
112 } else if constexpr (has_serializeOp<detail::remove_cvr_t<T>>::value) {
113 const_cast<T&>(data).serializeOp(*this);
114 } else {
116 m_packSize += m_packer.packSize(data);
117 else if (m_op == Operation::PACK)
118 m_packer.pack(data, m_buffer, m_position);
119 else if (m_op == Operation::UNPACK)
120 m_packer.unpack(const_cast<T&>(data), m_buffer, m_position);
121 }
122 }
123
127 template<class T>
128 void pack(const T& data)
129 {
131 m_packSize = 0;
132 (*this)(data);
133 m_position = 0;
134 m_buffer.resize(m_packSize);
136 (*this)(data);
137 }
138
142 template<class... Args>
143 void pack(const Args&... data)
144 {
146 m_packSize = 0;
147 variadic_call(data...);
148 m_position = 0;
149 m_buffer.resize(m_packSize);
151 variadic_call(data...);
152 }
153
157 template<class T>
158 void unpack(T& data)
159 {
160 m_position = 0;
162 (*this)(data);
163 }
164
168 template<class... Args>
169 void unpack(Args&... data)
170 {
171 m_position = 0;
173 variadic_call(data...);
174 }
175
177 size_t position() const
178 {
179 return m_position;
180 }
181
183 bool isSerializing() const
184 {
185 return m_op != Operation::UNPACK;
186 }
187
188protected:
190 template<typename Vector>
191 const typename Vector::value_type* getVectorData(const Vector& data)
192 {
193 if (data.size() == 0)
194 return nullptr;
195 else
196 return &(data[0]);
197 }
198
200 template<typename Vector>
201 typename Vector::value_type* getVectorData(Vector& data)
202 {
203 if (data.size() == 0)
204 return nullptr;
205 else
206 return &(data[0]);
207 }
211 template <typename Vector>
212 void vector(const Vector& data)
213 {
214 if constexpr (std::is_pod_v<typename Vector::value_type>) {
215 if (m_op == Operation::PACKSIZE) {
216 (*this)(data.size());
217 m_packSize += m_packer.packSize(data.data(), data.size());
218 } else if (m_op == Operation::PACK) {
219 (*this)(data.size());
220 m_packer.pack(getVectorData(data), data.size(), m_buffer, m_position);
221 } else if (m_op == Operation::UNPACK) {
222 std::size_t size = 0;
223 (*this)(size);
224 auto& data_mut = const_cast<Vector&>(data);
225 data_mut.resize(size);
227 }
228 } else {
229 if (m_op == Operation::UNPACK) {
230 std::size_t size = 0;
231 (*this)(size);
232 auto& data_mut = const_cast<Vector&>(data);
233 data_mut.resize(size);
234 std::for_each(data_mut.begin(), data_mut.end(), std::ref(*this));
235 } else {
236 (*this)(data.size());
237 std::for_each(data.begin(), data.end(), std::ref(*this));
238 }
239 }
240 }
241
244 void vector(const std::vector<bool>& data)
245 {
246 if (m_op == Operation::UNPACK) {
247 std::size_t size = 0;
248 (*this)(size);
249 auto& data_mut = const_cast<std::vector<bool>&>(data);
250 data_mut.clear();
251 data_mut.reserve(size);
252 for (size_t i = 0; i < size; ++i) {
253 bool entry = false;
254 (*this)(entry);
255 data_mut.push_back(entry);
256 }
257 } else {
258 (*this)(data.size());
259 for (const auto entry : data) { // Not a reference: vector<bool> range
260 bool b = entry;
261 (*this)(b);
262 }
263 }
264 }
265
268 template <class Array>
269 void array(const Array& data)
270 {
271 using T = typename Array::value_type;
272
273 if constexpr (std::is_pod_v<T>) {
275 m_packSize += m_packer.packSize(getVectorData(data), data.size());
276 else if (m_op == Operation::PACK)
277 m_packer.pack(getVectorData(data), data.size(), m_buffer, m_position);
278 else if (m_op == Operation::UNPACK) {
279 auto& data_mut = const_cast<Array&>(data);
281 }
282 } else {
283 std::for_each(data.begin(), data.end(), std::ref(*this));
284 }
285 }
286
289 template<class... Args>
290 void variant(const std::variant<Args...>& data)
291 {
292 if (m_op == Operation::UNPACK) {
293 std::size_t index = 0;
294 (*this)(index);
295 auto& data_mut = const_cast<std::variant<Args...>&>(data);
296 data_mut = detail::make_variant<Args...>(index);
297 std::visit(std::ref(*this), data_mut);
298 } else {
299 (*this)(data.index());
300 std::visit(std::ref(*this), data);
301 }
302 }
303
307 template<class T>
308 void optional(const std::optional<T>& data)
309 {
310 if (m_op == Operation::UNPACK) {
311 bool has = false;
312 (*this)(has);
313 if (has) {
314 T res{};
315 (*this)(res);
316 const_cast<std::optional<T>&>(data) = res;
317 }
318 } else {
319 (*this)(data.has_value());
320 if (data.has_value()) {
321 (*this)(*data);
322 }
323 }
324 }
325
328 template<class Tuple>
329 void tuple(const Tuple& data)
330 {
331 tuple_call(data);
332 }
333
337 template<class Map>
338 void map(const Map& data)
339 {
340 if (m_op == Operation::UNPACK) {
341 std::size_t size = 0;
342 (*this)(size);
343 auto& data_mut = const_cast<Map&>(data);
344 for (size_t i = 0; i < size; ++i) {
345 typename Map::value_type entry;
346 (*this)(entry);
347 data_mut.insert(entry);
348 }
349 } else {
350 (*this)(data.size());
351 std::for_each(data.begin(), data.end(), std::ref(*this));
352 }
353 }
354
358 template<class Set>
359 void set(const Set& data)
360 {
361 if (m_op == Operation::UNPACK) {
362 std::size_t size = 0;
363 (*this)(size);
364 auto& data_mut = const_cast<Set&>(data);
365 for (size_t i = 0; i < size; ++i) {
366 typename Set::value_type entry;
367 (*this)(entry);
368 data_mut.insert(entry);
369 }
370 } else {
371 (*this)(data.size());
372 std::for_each(data.begin(), data.end(), std::ref(*this));
373 }
374 }
375
376 template<typename T, typename... Args>
377 void variadic_call(T& first,
378 Args&&... args)
379 {
380 (*this)(first);
381 if constexpr (sizeof...(args) > 0)
382 variadic_call(std::forward<Args>(args)...);
383 }
384
385 template<std::size_t I = 0, typename Tuple>
386 typename std::enable_if<I == std::tuple_size<Tuple>::value, void>::type
387 tuple_call(const Tuple&)
388 {
389 }
390
391 template<std::size_t I = 0, typename Tuple>
392 typename std::enable_if<I != std::tuple_size<Tuple>::value, void>::type
393 tuple_call(const Tuple& tuple)
394 {
395 (*this)(std::get<I>(tuple));
397 }
398
400 enum class Operation {
401 PACKSIZE,
402 PACK,
403 UNPACK
404 };
405
407 template<class T>
408 struct is_vector {
409 constexpr static bool value = false;
410 };
411
412 template<class T1, class Allocator>
413 struct is_vector<std::vector<T1,Allocator>> {
414 constexpr static bool value = true;
415 };
416
417#if HAVE_DUNE_ISTL
418 template<class T1, class Allocator>
419 struct is_vector<Dune::BlockVector<T1,Allocator>> {
420 constexpr static bool value = true;
421 };
422#endif
423
425 template<class T>
426 struct is_variant {
427 constexpr static bool value = false;
428 };
429
430 template<class... Ts>
431 struct is_variant<std::variant<Ts...>> {
432 constexpr static bool value = true;
433 };
434
436 template<class T>
438 constexpr static bool value = false;
439 };
440
441 template<class... Ts>
442 struct is_pair_or_tuple<std::tuple<Ts...>> {
443 constexpr static bool value = true;
444 };
445
446 template<class T1, class T2>
447 struct is_pair_or_tuple<std::pair<T1,T2>> {
448 constexpr static bool value = true;
449 };
450
452 template<class T>
453 struct is_ptr {
454 constexpr static bool value = false;
455 };
456
457 template<class T1>
458 struct is_ptr<std::shared_ptr<T1>> {
459 constexpr static bool value = true;
460 };
461
462 template<class T1, class Deleter>
463 struct is_ptr<std::unique_ptr<T1, Deleter>> {
464 constexpr static bool value = true;
465 };
466
468 template<class T>
469 struct is_optional {
470 constexpr static bool value = false;
471 };
472
473 template<class T1>
474 struct is_optional<std::optional<T1>> {
475 constexpr static bool value = true;
476 };
477
479 template<class T>
480 struct is_map {
481 constexpr static bool value = false;
482 };
483
484 template<class Key, class T, class Compare, class Allocator>
485 struct is_map<std::map<Key,T,Compare,Allocator>> {
486 constexpr static bool value = true;
487 };
488
489 template<class Key, class T, class Hash, class KeyEqual, class Allocator>
490 struct is_map<std::unordered_map<Key,T,Hash,KeyEqual,Allocator>> {
491 constexpr static bool value = true;
492 };
493
495 template<class T>
496 struct is_set {
497 constexpr static bool value = false;
498 };
499
500 template<class Key, class Compare, class Allocator>
501 struct is_set<std::set<Key,Compare,Allocator>> {
502 constexpr static bool value = true;
503 };
504
505 template<class Key, class Hash, class KeyEqual, class Allocator>
506 struct is_set<std::unordered_set<Key,Hash,KeyEqual,Allocator>> {
507 constexpr static bool value = true;
508 };
509
511 template<class T>
512 struct is_array {
513 constexpr static bool value = false;
514 };
515
516 template<class T, std::size_t N>
517 struct is_array<std::array<T,N>> {
518 constexpr static bool value = true;
519 };
520
521#if HAVE_DUNE_COMMON
522 template<class T, int N>
523 struct is_array<Dune::FieldVector<T,N>> {
524 constexpr static bool value = true;
525 };
526#endif
527
531 template <typename, class = void>
532 struct has_serializeOp : public std::false_type {};
533
538 template <typename T>
540 T, std::void_t<decltype(std::declval<T>().serializeOp(std::declval<Serializer<Packer>&>()))>
541 > : public std::true_type {};
542
544 template<class PtrType>
545 void ptr(const PtrType& data)
546 {
547 using T1 = typename PtrType::element_type;
548 bool value = data ? true : false;
549 (*this)(value);
550 if (m_op == Operation::UNPACK && value) {
551 const_cast<PtrType&>(data).reset(new T1);
552 }
553 if (data) {
554 (*this)(*data);
555 }
556 }
557
560 size_t m_packSize = 0;
561 int m_position = 0;
562 std::vector<char> m_buffer;
563};
564
565}
566
567#endif
Class for (de-)serializing.
Definition Serializer.hpp:84
void ptr(const PtrType &data)
Handler for smart pointers.
Definition Serializer.hpp:545
void array(const Array &data)
Handler for arrays.
Definition Serializer.hpp:269
void operator()(const T &data)
Applies current serialization op to the passed data.
Definition Serializer.hpp:94
bool isSerializing() const
Returns true if we are currently doing a serialization operation.
Definition Serializer.hpp:183
const Packer & m_packer
Packer to use.
Definition Serializer.hpp:558
void tuple(const Tuple &data)
Handler for std::tuple.
Definition Serializer.hpp:329
void set(const Set &data)
Handler for sets.
Definition Serializer.hpp:359
Operation
Enumeration of operations.
Definition Serializer.hpp:400
@ UNPACK
Performing de-serialization.
@ PACKSIZE
Calculating serialization buffer size.
@ PACK
Performing serialization.
void unpack(T &data)
Call this to de-serialize data.
Definition Serializer.hpp:158
size_t position() const
Returns current position in buffer.
Definition Serializer.hpp:177
const Vector::value_type * getVectorData(const Vector &data)
Utility function for missing data() member function in FieldVector of DUNE 2.6.
Definition Serializer.hpp:191
size_t m_packSize
Required buffer size after PACKSIZE has been done.
Definition Serializer.hpp:560
void pack(const Args &... data)
Call this to serialize data.
Definition Serializer.hpp:143
void unpack(Args &... data)
Call this to de-serialize data.
Definition Serializer.hpp:169
void vector(const Vector &data)
Handler for vectors.
Definition Serializer.hpp:212
void vector(const std::vector< bool > &data)
Handler for bool vectors.
Definition Serializer.hpp:244
Serializer(const Packer &packer)
Constructor.
Definition Serializer.hpp:88
void variant(const std::variant< Args... > &data)
Handler for std::variant.
Definition Serializer.hpp:290
Vector::value_type * getVectorData(Vector &data)
Utility function for missing data() member function in FieldVector of DUNE 2.6.
Definition Serializer.hpp:201
void map(const Map &data)
Handler for maps.
Definition Serializer.hpp:338
void pack(const T &data)
Call this to serialize data.
Definition Serializer.hpp:128
Operation m_op
Current operation.
Definition Serializer.hpp:559
void optional(const std::optional< T > &data)
Handler for std::optional.
Definition Serializer.hpp:308
int m_position
Current position in buffer.
Definition Serializer.hpp:561
std::vector< char > m_buffer
Buffer for serialized data.
Definition Serializer.hpp:562
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition Exceptions.hpp:30
Detect existence of serializeOp member function.
Definition Serializer.hpp:532
Predicate for arrays.
Definition Serializer.hpp:512
Predicate for maps.
Definition Serializer.hpp:480
Predicate for std::optional.
Definition Serializer.hpp:469
Predicate for detecting pairs and tuples.
Definition Serializer.hpp:437
Predicate for smart pointers.
Definition Serializer.hpp:453
Predicate for sets.
Definition Serializer.hpp:496
Predicate for detecting variants.
Definition Serializer.hpp:426
Predicate for detecting vectors.
Definition Serializer.hpp:408
Definition Serializer.hpp:51