TPIE

v1.1rc1-6-g0c97303
serialization.h
Go to the documentation of this file.
1 // -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*-
2 // vi:set ts=4 sts=4 sw=4 noet :
3 // Copyright 2010, The TPIE development team
4 //
5 // This file is part of TPIE.
6 //
7 // TPIE is free software: you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License as published by the
9 // Free Software Foundation, either version 3 of the License, or (at your
10 // option) any later version.
11 //
12 // TPIE is distributed in the hope that it will be useful, but WITHOUT ANY
13 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 // License for more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public License
18 // along with TPIE. If not, see <http://www.gnu.org/licenses/>
19 #ifndef __TPIE_SERIALIZATION_H__
20 #define __TPIE_SERIALIZATION_H__
21 
25 
26 #include <tpie/config.h>
27 #include <tpie/portability.h>
28 #include <tpie/hash_map.h>
29 #include <vector>
30 #include <utility>
31 #include <typeinfo>
32 
33 #include <boost/type_traits/is_fundamental.hpp>
34 #include <boost/type_traits/is_enum.hpp>
35 #include <boost/utility/enable_if.hpp>
36 #include <boost/cstdint.hpp>
37 #include <istream>
38 #include <ostream>
39 #include <cstring>
40 
41 namespace tpie {
42 
43 #ifndef DOXYGEN
44 template <bool b1, bool b2>
45 struct _disjunction: public boost::true_type {};
46 
47 template <>
48 struct _disjunction<false, false>: public boost::false_type {};
49 #endif
50 
54 template <typename T1, typename T2>
55 struct disjunction: public _disjunction<T1::value, T2::value> {};
56 
57 struct serialization_error: public std::runtime_error {
58  explicit serialization_error(const std::string & what): std::runtime_error(what) {}
59 };
60 
61 
62 
67 class serializer {
68 public:
72  serializer(std::ostream & out, bool typesafe=false): m_out(out), m_typesafe(false) {
73  *this << "TPIE Serialization" //File header
74  << (boost::uint16_t)1 //File version
75  << typesafe; //Do we serialize typeids before each actual item?
76  m_typesafe = typesafe;
77  }
78 
79  template <typename T>
80  inline serializer & write(const T * data, size_t l) {
81  *this << (boost::uint16_t)l;
82  for (size_t i=0; i < l; ++i)
83  *this << data[i];
84  return *this;
85  }
86  template <typename T>
87  inline typename boost::enable_if<disjunction<boost::is_fundamental<T>, boost::is_enum<T> > ,
88  serializer &>::type operator << (const T & x) {
89  write_type<T>();
90  m_out.write(reinterpret_cast<const char*>(&x), sizeof(T));
91  return * this;
92  }
93 
94  template <typename T1, typename T2>
95  inline serializer & operator <<(const std::pair<T1, T2> & p) {
96  write_type<std::pair<T1,T2> >();
97  return *this << p.first << p.second;
98  }
99 
100  template <typename T>
101  inline serializer & operator <<(const std::vector<T> & v) {
102  write_type<std::vector<T> >();
103  *this << (boost::uint16_t)v.size();
104  for (size_t i=0; i < v.size(); ++i)
105  *this << v[i];
106  return *this;
107  }
108 
109  inline serializer & operator <<(const char * data) {write_type<std::string>(); return write(data, strlen(data));}
110  inline serializer & operator <<(const std::string & s) {write_type<std::string>(); return write(s.c_str(), s.size());}
111 private:
112  template <typename T>
113  void write_type() {
114  if (m_typesafe) {
115  hash<const char *> h;
116  m_out << (uint8_t)(h(typeid(T).name()) % 256);
117  }
118  }
119 
120  std::ostream & m_out;
121  bool m_typesafe;
122 };
123 
130 public:
134  unserializer(std::istream & in): m_in(in), m_typesafe(false) {
135  //Validate header;
136  *this << "TPIE Serialization"
137  << (boost::uint16_t)1;
138  bool typesafe;
139  *this >> typesafe;
140  m_typesafe=typesafe;
141  }
142 
143  template <typename T>
144  inline unserializer & operator <<(const T & x) {
145  T y;
146  *this >> y;
147  if (y != x) throw serialization_error("Verification failed");
148  return *this;
149  }
150 
151  inline unserializer & operator <<(const char * x) {
152  std::string y;
153  *this >> y;
154  if (y != x) throw serialization_error("Verification failed");
155  return *this;
156  }
157 
158  template <typename T>
159  inline unserializer & read(T * array, size_t & size) {
160  boost::uint16_t x;
161  *this >> x;
162  if (x > size) throw serialization_error("array too short");
163  size=x;
164  for (size_t i=0; i < size; ++i)
165  *this >> array[i];
166  return *this;
167  }
168 
169  template <typename T>
170  inline typename boost::enable_if<disjunction<boost::is_fundamental<T>, boost::is_enum<T> >, unserializer &>::type operator >> (T & x) {
171  check_type<T>();
172  char * y = reinterpret_cast<char*>(&x);
173  m_in.read(y, sizeof(T));
174  if (m_in.eof() || m_in.fail()) throw serialization_error("Unexpected end-of-file");
175  return *this;
176  }
177 
178  template <typename T1, typename T2>
179  inline unserializer & operator >>(std::pair<T1, T2> & p) {
180  check_type<std::pair<T1, T2> >();
181  return *this >> p.first >> p.second;
182  }
183 
184  template <typename T>
185  inline unserializer & operator >> (std::vector<T> & v) {
186  check_type<std::vector<T> >();
187  boost::uint16_t size;
188  *this >> size;
189  v.clear();
190  for (size_t i=0; i < size; ++i) {
191  v.push_back(T());
192  *this >> v.back();
193  }
194  return *this;
195  }
196 
197  inline unserializer & operator >>(std::string & s) {
198  check_type<std::string>();
199  s.clear();
200  boost::uint16_t size;
201  *this >> size;
202  for (size_t i=0; i < size; ++i) {
203  char x;
204  *this >> x;
205  s.push_back(x);
206  }
207  return *this;
208  }
209 
210 private:
211  template <typename T>
212  void check_type() {
213  if (!m_typesafe) return;
214  hash<const char *> h;
215  uint8_t hash = h(typeid(T).name()) % 256;
216  uint8_t s_hash;
217  m_in >> s_hash;
218  if (s_hash == hash) return;
219  std::stringstream ss;
220  ss << "Serialization type error, input type did not match expected type: " << typeid(T).name();
221  throw serialization_error(ss.str());
222  }
223 
224  std::istream & m_in;
225  bool m_typesafe;
226 };
227 
228 } //namespace tpie
229 #endif /*__TPIE_SERIALIZATION_H__*/
Class to compute the disjunction between two boost true/false types.
Definition: serialization.h:55
unserializer(std::istream &in)
Construct a unserializer reading from the std::istream in.
This file contains a few deprecated definitions for legacy code.
Class providing binary serialization to a std::ostream.
Definition: serialization.h:67
Internal hash map with guaranteed memory requirements.
serializer(std::ostream &out, bool typesafe=false)
Construct a serializer writing to out.
Definition: serialization.h:72
Class for unserializing binary data serialized with the serializer Data can be unserialized using the...