Line data Source code
1 : /*
2 : * Copyright (c) 2010-2015: G-CSC, Goethe University Frankfurt
3 : * Authors: Sebastian Reiter, Martin Rupp
4 : *
5 : * This file is part of UG4.
6 : *
7 : * UG4 is free software: you can redistribute it and/or modify it under the
8 : * terms of the GNU Lesser General Public License version 3 (as published by the
9 : * Free Software Foundation) with the following additional attribution
10 : * requirements (according to LGPL/GPL v3 §7):
11 : *
12 : * (1) The following notice must be displayed in the Appropriate Legal Notices
13 : * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 : *
15 : * (2) The following notice must be displayed at a prominent place in the
16 : * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 : *
18 : * (3) The following bibliography is recommended for citation and must be
19 : * preserved in all covered files:
20 : * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 : * parallel geometric multigrid solver on hierarchically distributed grids.
22 : * Computing and visualization in science 16, 4 (2013), 151-164"
23 : * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 : * flexible software system for simulating pde based models on high performance
25 : * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 : *
27 : * This program is distributed in the hope that it will be useful,
28 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 : * GNU Lesser General Public License for more details.
31 : */
32 :
33 : #ifndef __H__UG__SERIALIZATION__
34 : #define __H__UG__SERIALIZATION__
35 :
36 : #include <iostream>
37 : #include <vector>
38 : #include <set>
39 : #include <map>
40 : #include <string>
41 : #include <cassert>
42 : #include "log.h"
43 : #include "util/variant.h"
44 : #include "error.h"
45 :
46 : namespace ug
47 : {
48 :
49 : /// \addtogroup ugbase_common
50 : /// \{
51 :
52 : //todo It would probably be a good idea to replace the generic Serialize and
53 : // Deserialize methods with concrete ones, since nasty and hard to trace
54 : // bugs could be avoided this way. The following Serialize methods already
55 : // implement serialization for common types. A rather big effort for all
56 : // the custom types which have to be serialized has to be taken though...
57 : /*
58 : template <class TStream>
59 : void Serialize(TStream& buf, const bool& val)
60 : {
61 : buf.write((char*)&val, sizeof(bool));
62 : }
63 :
64 : template <class TStream>
65 : void Deserialize(TStream& buf, bool& valOut)
66 : {
67 : buf.read((char*)&valOut, sizeof(bool));
68 : }
69 :
70 : template <class TStream>
71 : void Serialize(TStream& buf, const char& val)
72 : {
73 : buf.write((char*)&val, sizeof(char));
74 : }
75 :
76 : template <class TStream>
77 : void Deserialize(TStream& buf, char& valOut)
78 : {
79 : buf.read((char*)&valOut, sizeof(char));
80 : }
81 :
82 : template <class TStream>
83 : void Serialize(TStream& buf, const unsigned char& val)
84 : {
85 : buf.write((char*)&val, sizeof(unsigned char));
86 : }
87 :
88 : template <class TStream>
89 : void Deserialize(TStream& buf, unsigned char& valOut)
90 : {
91 : buf.read((char*)&valOut, sizeof(unsigned char));
92 : }
93 :
94 : template <class TStream>
95 : void Serialize(TStream& buf, const int& val)
96 : {
97 : buf.write((char*)&val, sizeof(int));
98 : }
99 :
100 : template <class TStream>
101 : void Deserialize(TStream& buf, int& valOut)
102 : {
103 : buf.read((char*)&valOut, sizeof(int));
104 : }
105 :
106 : template <class TStream>
107 : void Serialize(TStream& buf, const unsigned int& val)
108 : {
109 : buf.write((char*)&val, sizeof(unsigned int));
110 : }
111 :
112 : template <class TStream>
113 : void Deserialize(TStream& buf, unsigned int& valOut)
114 : {
115 : buf.read((char*)&valOut, sizeof(unsigned int));
116 : }
117 :
118 : template <class TStream>
119 : void Serialize(TStream& buf, const size_t& val)
120 : {
121 : buf.write((char*)&val, sizeof(size_t));
122 : }
123 :
124 : template <class TStream>
125 : void Deserialize(TStream& buf, size_t& valOut)
126 : {
127 : buf.read((char*)&valOut, sizeof(size_t));
128 : }
129 :
130 : template <class TStream>
131 : void Serialize(TStream& buf, const float& val)
132 : {
133 : buf.write((char*)&val, sizeof(float));
134 : }
135 :
136 : template <class TStream>
137 : void Deserialize(TStream& buf, float& valOut)
138 : {
139 : buf.read((char*)&valOut, sizeof(float));
140 : }
141 :
142 : template <class TStream>
143 : void Serialize(TStream& buf, const double& val)
144 : {
145 : buf.write((char*)&val, sizeof(int));
146 : }
147 :
148 : template <class TStream>
149 : void Deserialize(TStream& buf, double& valOut)
150 : {
151 : buf.read((char*)&valOut, sizeof(double));
152 : }
153 : */
154 :
155 : template <class TStream, class T>
156 : void Serialize(TStream& buf, const T& val)
157 : {
158 0 : buf.write((char*)&val, sizeof(T));
159 : }
160 :
161 : template <class TStream, class T>
162 : void Deserialize(TStream& buf, T& valOut)
163 : {
164 0 : buf.read((char*)&valOut, sizeof(T));
165 : }
166 :
167 : /// method returning value directly
168 : template<typename T, class TIStream>
169 0 : T Deserialize(TIStream &stream)
170 : {
171 : T t;
172 0 : Deserialize(stream, t);
173 0 : return t;
174 : }
175 :
176 : /// Catch errors with wrong const identifiers in valOut.
177 : /** This method isn't implemented on purpose!*/
178 : template <class TStream, class T>
179 : void Deserialize(TStream& buf, const T& valOut);
180 :
181 :
182 : ////////////////////////////////////////////////////////////////////////////////
183 : // All specializations should be pre-declared here!
184 : // This is important, so that the different methods know of each other.
185 : template <class T1, class T2, class TOStream>
186 : void Serialize(TOStream& buf, const std::pair<T1, T2>& v);
187 :
188 : template <class T1, class T2, class TIStream>
189 : void Deserialize(TIStream& buf, std::pair<T1, T2>& v);
190 :
191 : template <class T, class TOStream>
192 : void Serialize(TOStream& buf, const std::set<T>& m);
193 :
194 : template <class T, class TIStream>
195 : void Deserialize(TIStream& buf, std::set<T>& myset);
196 :
197 : template <class TOStream>
198 : void Serialize(TOStream& buf, const std::string& str);
199 :
200 : template <class TIStream>
201 : void Deserialize(TIStream& buf, std::string& str);
202 :
203 : template <class TOStream>
204 : void Serialize(TOStream& buf, const Variant& v);
205 :
206 : template <class TIStream>
207 : void Deserialize(TIStream& buf, Variant& v);
208 :
209 : template <class T, class TOStream>
210 : void Serialize(TOStream& buf, const std::vector<T>& vec);
211 :
212 : template <class T, class TIStream>
213 : void Deserialize(TIStream& buf, std::vector<T>& vec);
214 :
215 : template <class TOStream>
216 : inline void Serialize(TOStream& buf, const std::vector<bool>::reference& boolRef);
217 :
218 : template <class TIStream>
219 : inline void Deserialize(TIStream& buf, std::vector<bool>::reference boolRef);
220 :
221 : template <class Key, class T, class TOStream>
222 : void Serialize(TOStream& buf, const std::map<Key, T>& m);
223 :
224 : template <class Key, class T, class TIStream>
225 : void Deserialize(TIStream& buf, std::map<Key, T>& m);
226 : ////////////////////////////////////////////////////////////////////////////////
227 :
228 :
229 :
230 : ////////////////////////////////////////////////////////////////////////////////
231 : template <class T1, class T2, class TOStream>
232 0 : void Serialize(TOStream& buf, const std::pair<T1, T2>& v)
233 : {
234 0 : Serialize(buf, v.first);
235 0 : Serialize(buf, v.second);
236 0 : }
237 :
238 : template <class T1, class T2, class TIStream>
239 0 : void Deserialize(TIStream& buf, std::pair<T1, T2>& v)
240 : {
241 0 : Deserialize(buf, v.first);
242 0 : Deserialize(buf, v.second);
243 0 : }
244 :
245 : /// writes data from a set to a binary stream
246 : /** This template method is used in ug when it comes to writing data
247 : * from a map into a binary stream.
248 : * In its default implementation, it first writes the size of the map
249 : * and then serializes the entries.
250 : */
251 : template <class T, class TOStream>
252 : void Serialize(TOStream& buf, const std::set<T>& m)
253 : {
254 : Serialize<size_t>(buf, m.size());
255 : for(typename std::set<T>::const_iterator it = m.begin(); it != m.end(); ++it)
256 : Serialize<T>(buf, *it);
257 : }
258 :
259 : /// deserializes data from a binary stream into a set
260 : template <class T, class TIStream>
261 : void Deserialize(TIStream& buf, std::set<T>& myset)
262 : {
263 : myset.clear();
264 : size_t size = Deserialize<size_t>(buf);
265 : T t;
266 : for(size_t i = 0; i < size; ++i)
267 : {
268 : Deserialize<T>(buf, t);
269 : // using myset.end() because data t is sorted.
270 : myset.insert (myset.end(), t);
271 : }
272 : }
273 :
274 : /// Writes a string to a binary stream
275 : /** First the length of the string is written, then its content.*/
276 : template <class TOStream>
277 0 : void Serialize(TOStream& buf, const std::string& str)
278 : {
279 0 : size_t len = str.length();
280 : Serialize(buf, len);
281 0 : if(len > 0)
282 0 : buf.write(str.c_str(), sizeof(char) * len);
283 0 : }
284 :
285 : /// deserializes data from a binary stream into a string
286 : template <class TIStream>
287 0 : void Deserialize(TIStream& buf, std::string& str)
288 : {
289 : // the buffers allow us to read small strings fast.
290 : // for bigger ones we have to temporarily reserve memory.
291 : char staticBuf[64];
292 : char* flexBuf = NULL;
293 : char* tBuf = staticBuf;
294 :
295 : size_t len = Deserialize<size_t>(buf);
296 :
297 : // check whether we have to allocate memory
298 : // don't forget that we have to append a zero at the end
299 0 : if(len >= 63){
300 0 : flexBuf = new char[len + 1];
301 : tBuf = flexBuf;
302 : }
303 :
304 0 : if(len > 0)
305 0 : buf.read(tBuf, sizeof(char) * len);
306 0 : tBuf[len] = 0;
307 :
308 : // assign data to the out-string
309 : str = tBuf;
310 :
311 : // clean up
312 0 : if(flexBuf)
313 0 : delete[] flexBuf;
314 0 : }
315 :
316 :
317 : /// serializes a variant
318 : /** Note that pointers can't be serialized in a meaningful way. We thus simply
319 : * do not serialize them. During deserialization pointers will be set to NULL.
320 : *
321 : * Note that c-strings (const char*) are converted to std::strings before
322 : * serialization. This means that they will be deserialized as std::string
323 : */
324 : template <class TOStream>
325 0 : void Serialize(TOStream& buf, const Variant& v)
326 : {
327 0 : Serialize(buf, int(v.type()));
328 0 : switch(v.type()){
329 : case Variant::VT_INVALID: break;
330 0 : case Variant::VT_BOOL: Serialize(buf, v.to_bool()); break;
331 0 : case Variant::VT_INT: Serialize(buf, v.to_int()); break;
332 0 : case Variant::VT_FLOAT: Serialize(buf, v.to_float()); break;
333 0 : case Variant::VT_DOUBLE: Serialize(buf, v.to_double()); break;
334 0 : case Variant::VT_CSTRING: Serialize(buf, std::string(v.to_c_string())); break;
335 0 : case Variant::VT_STDSTRING: Serialize(buf, v.to_std_string()); break;
336 : case Variant::VT_POINTER: break;
337 :
338 0 : default:
339 0 : UG_THROW("Unknown variant type in Serialize:" << v.type());
340 : break;
341 : }
342 0 : }
343 :
344 : /// deserializes data from a binary stream into a variant
345 : /** Note that pointers can't be serialized in a meaningful way. We thus simply
346 : * do not serialize them. During deserialization pointers will be set to NULL.
347 : */
348 : template <class TIStream>
349 0 : void Deserialize(TIStream& buf, Variant& v)
350 : {
351 : int type = Deserialize<int>(buf);
352 0 : switch(type){
353 0 : case Variant::VT_INVALID: v = Variant(); break;
354 0 : case Variant::VT_BOOL: v = Variant(Deserialize<bool>(buf)); break;
355 0 : case Variant::VT_INT: v = Variant(Deserialize<int>(buf)); break;
356 0 : case Variant::VT_FLOAT: v = Variant(Deserialize<float>(buf)); break;
357 0 : case Variant::VT_DOUBLE: v = Variant(Deserialize<double>(buf)); break;
358 0 : case Variant::VT_CSTRING: // fallthrough
359 0 : case Variant::VT_STDSTRING: v = Variant(Deserialize<std::string>(buf)); break;
360 :
361 0 : case Variant::VT_POINTER:{
362 : void* val = NULL;
363 0 : v = Variant(val);
364 0 : } break;
365 :
366 0 : default:
367 0 : UG_THROW("Unknown variant type in Deserialize: " << type);
368 : break;
369 : }
370 0 : }
371 :
372 : /// writes data in a vector to a binary stream
373 : /** This template method is used in ug when it comes to writing data
374 : * from a vector into a binary stream.
375 : * In its default implementation, it first writes the size of the vector
376 : * and then serializes the entries.
377 : */
378 : template <class T, class TOStream>
379 : void Serialize(TOStream& buf, const std::vector<T>& vec)
380 : {
381 : size_t size = vec.size();
382 : Serialize(buf, size);
383 : for(size_t i = 0; i < size; ++i){
384 : Serialize(buf, vec[i]);
385 : }
386 : }
387 :
388 : /// deserializes data from a binary stream into a vector
389 : template <class T, class TIStream>
390 : void Deserialize(TIStream& buf, std::vector<T>& vec)
391 : {
392 : vec.clear();
393 : size_t size = Deserialize<size_t>(buf);
394 : vec.resize(size);
395 : for(size_t i = 0; i < size; ++i){
396 : Deserialize(buf, vec[i]);
397 : }
398 : }
399 :
400 :
401 : template<class TIStream>
402 : void Serialize(TIStream &buf, const std::vector<bool> &vec)
403 : {
404 : size_t size=vec.size();
405 : Serialize<size_t>(buf, size);
406 : int j=0;
407 : char a=0;
408 : for(size_t i = 0; i < size; ++i)
409 : {
410 : if(vec[i]) a |= (1 << j);
411 : if(++j == 8)
412 : {
413 : Serialize<char>(buf, a);
414 : a = 0;
415 : j = 0;
416 : }
417 : }
418 : if(j) Serialize<char>(buf, a);
419 : }
420 :
421 : template<class TIStream>
422 : void Deserialize(TIStream &buf, std::vector<bool> &vec)
423 : {
424 : vec.clear();
425 : size_t size = Deserialize<size_t>(buf);
426 : vec.resize(size);
427 : int j=8;
428 : char a=0;
429 : for(size_t i = 0; i < size; ++i, ++j)
430 : {
431 : if(j==8)
432 : {
433 : Deserialize<char>(buf, a);
434 : j=0;
435 : }
436 : vec[i] = a & (1 << j);
437 : j++;
438 : }
439 : }
440 :
441 : /** This method is used in ug when it comes to writing data
442 : * from a vector<bool> into a binary stream.
443 : * This function is to avoid surprises with vector<bool>
444 : * because of vector<bool>::reference.
445 : * Note: You could also define Serialize(., vector<bool>::reference)
446 : */
447 : template <class TOStream>
448 : inline void Serialize(TOStream& buf, const std::vector<bool>::reference& boolRef)
449 : {
450 0 : char b = ((bool)boolRef) ? 1 : 0;
451 0 : buf.write(&b, sizeof(char));
452 : }
453 :
454 : /// deserializes data from a binary stream into a vector<bool>
455 : // * This function is to avoid surprises with vector<bool>
456 : // note: boolRef is not &boolRef.
457 : template <class TIStream>
458 0 : inline void Deserialize(TIStream& buf, std::vector<bool>::reference boolRef)
459 : {
460 : char b;
461 0 : buf.read(&b, sizeof(char));
462 0 : boolRef = (bool)(b == 1);
463 0 : }
464 :
465 :
466 : /// writes data from a map to a binary stream
467 : /** This template method is used in ug when it comes to writing data
468 : * from a map into a binary stream.
469 : * In its default implementation, it first writes the size of the map
470 : * and then serializes the entries.
471 : */
472 : template <class Key, class T, class TOStream>
473 0 : void Serialize(TOStream& buf, const std::map<Key, T>& m)
474 : {
475 0 : Serialize(buf, m.size());
476 :
477 0 : for(typename std::map<Key, T>::const_iterator it = m.begin(); it != m.end(); ++it)
478 : {
479 0 : Serialize(buf, it->first);
480 0 : Serialize(buf, it->second);
481 : }
482 0 : }
483 :
484 : /// deserializes data from a binary stream into a map
485 : template <class Key, class T, class TIStream>
486 0 : void Deserialize(TIStream& buf, std::map<Key, T>& m)
487 : {
488 : m.clear();
489 : size_t size = Deserialize<size_t>(buf);
490 0 : for(size_t i = 0; i < size; ++i)
491 : {
492 : Key k;
493 0 : Deserialize(buf, k);
494 0 : Deserialize(buf, m[k]);
495 : }
496 0 : }
497 :
498 : // end group ugbase_common
499 : /// \}
500 :
501 : }// end of namespace
502 :
503 :
504 : #endif
|