LCOV - code coverage report
Current view: top level - ugbase/common - serialization.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 71 0
Test Date: 2025-09-21 23:31:46 Functions: 0.0 % 10 0

            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
        

Generated by: LCOV version 2.0-1