A toolkit for working with phylogenetic data.
v0.18.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
utils/io/serializer.hpp
Go to the documentation of this file.
1 #ifndef GENESIS_UTILS_IO_SERIALIZER_H_
2 #define GENESIS_UTILS_IO_SERIALIZER_H_
3 
4 /*
5  Genesis - A toolkit for working with phylogenetic data.
6  Copyright (C) 2014-2017 Lucas Czech
7 
8  This program is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 3 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program. If not, see <http://www.gnu.org/licenses/>.
20 
21  Contact:
22  Lucas Czech <lucas.czech@h-its.org>
23  Exelixis Lab, Heidelberg Institute for Theoretical Studies
24  Schloss-Wolfsbrunnenweg 35, D-69118 Heidelberg, Germany
25 */
26 
39 
40 #include <algorithm>
41 #include <cstring>
42 #include <fstream>
43 #include <iostream>
44 #include <stdexcept>
45 #include <string>
46 
47 namespace genesis {
48 namespace utils {
49 
50 // =================================================================================================
51 // Serializer
52 // =================================================================================================
53 
58 {
59 public:
60 
61  // -------------------------------------------------------------------------
62  // Constructor and Destructor
63  // -------------------------------------------------------------------------
64 
65  Serializer (const std::string& filename) :
67  {
68  utils::file_output_stream( filename, outfile, std::ofstream::out | std::ofstream::binary );
69  };
70 
71  Serializer (std::ostream& outstream) :
72  outstream (outstream)
73  {};
74 
76  {
77  outfile.close();
78  }
79 
80  // -------------------------------------------------------------------------
81  // Stream Status
82  // -------------------------------------------------------------------------
83 
84  inline operator bool() const
85  {
86  return !outstream.fail();
87  }
88 
89  inline bool good() const
90  {
91  return outstream.good();
92  }
93 
94  inline bool eof() const
95  {
96  return outstream.eof();
97  }
98 
99  inline bool fail() const
100  {
101  return outstream.fail();
102  }
103 
104  inline bool bad() const
105  {
106  return outstream.bad();
107  }
108 
109  // -------------------------------------------------------------------------
110  // File Status
111  // -------------------------------------------------------------------------
112 
113  inline bool is_open() const
114  {
115  return outfile.is_open();
116  }
117 
118  inline void flush()
119  {
120  outfile.flush();
121  }
122 
123  inline void close()
124  {
125  outfile.close();
126  }
127 
128  // -------------------------------------------------------------------------
129  // Serialization
130  // -------------------------------------------------------------------------
131 
135  void put_null (const size_t n)
136  {
137  char* buffer = new char[n];
138  std::fill(buffer, buffer+n, '\0');
139  outstream.write (buffer, n);
140  delete[] buffer;
141  }
142 
146  void put_raw( char const* data, size_t n )
147  {
148  outstream.write (data, n);
149  }
150 
154  void put_raw_string (const std::string& v)
155  {
156  outstream.write (v.c_str(), v.length());
157  }
158 
162  void put_string (const std::string& v)
163  {
164  size_t len = v.length();
165  put_int(len);
166  put_raw_string(v);
167  }
168 
172  template<typename T>
173  void put_plain (const T v)
174  {
175  outstream.write((char*)(&v), sizeof(v));
176  }
177 
184  template<typename T>
185  void put_int (const T v)
186  {
187  put_plain(v);
188  }
189 
196  template<typename T>
197  void put_float (const T v)
198  {
199  put_plain(v);
200  }
201 
202  // -------------------------------------------------------------------------
203  // Data Members
204  // -------------------------------------------------------------------------
205 
206 protected:
207  std::ofstream outfile;
208  std::ostream& outstream;
209 };
210 
211 // =================================================================================================
212 // Deserializer
213 // =================================================================================================
214 
219 {
220 public:
221 
222  // -------------------------------------------------------------------------
223  // Constructor and Destructor
224  // -------------------------------------------------------------------------
225 
226  Deserializer( std::string const& file_name )
227  : buffer_( utils::make_unique< FileInputSource >( file_name ) )
228  {
229  if( ! buffer_ ) {
230  throw std::runtime_error("Creating Deserializer from file failed.");
231  }
232  }
233 
234  Deserializer( std::istream& instream )
235  : buffer_( utils::make_unique< StreamInputSource >( instream ) )
236  {
237  if( ! buffer_ ) {
238  throw std::runtime_error("Creating Deserializer from stream failed.");
239  }
240  }
241 
242  // -------------------------------------------------------------------------
243  // Stream Status
244  // -------------------------------------------------------------------------
245 
246  inline operator bool() const
247  {
248  return buffer_;
249  }
250 
251  // inline bool good() const
252  // {
253  // return instream.good();
254  // }
255  //
256  // inline bool eof() const
257  // {
258  // return instream.eof();
259  // }
260  //
261  // inline bool fail() const
262  // {
263  // return instream.fail();
264  // }
265  //
266  // inline bool bad() const
267  // {
268  // return instream.bad();
269  // }
270  //
271  // inline bool succeeded() const
272  // {
273  // return !instream.eof() && instream.peek() == EOF;
274  // }
275 
276  inline bool finished() const
277  {
278  return ! buffer_;
279  }
280 
281  // -------------------------------------------------------------------------
282  // File Status
283  // -------------------------------------------------------------------------
284 
285  // inline bool is_open() const
286  // {
287  // return infile.is_open();
288  // }
289  //
290  // inline void close()
291  // {
292  // infile.close();
293  // }
294 
295  // -------------------------------------------------------------------------
296  // Deserialization
297  // -------------------------------------------------------------------------
298 
304  void get_raw(char* buffer, size_t n)
305  {
306  size_t const got = buffer_.read(buffer, n);
307  if( got != n ) {
308  throw std::runtime_error(
309  "Could only read " + std::to_string(got) + " bytes instead of n=" +
310  std::to_string( n ) + " bytes from Deserializer input."
311  );
312  }
313  }
314 
318  bool get_null (size_t n)
319  {
320  char* buffer = new char[n];
321  get_raw( buffer, n );
322 
323  bool ret = true;
324  for (size_t i = 0; i < n; ++i) {
325  ret &= (buffer[i] == '\0');
326  }
327 
328  delete[] buffer;
329  return ret;
330  }
331 
335  std::string get_raw_string(size_t n)
336  {
337  char* buffer = new char[n];
338  get_raw( buffer, n );
339 
340  std::string str (buffer, n);
341  delete[] buffer;
342  return str;
343  }
344 
349  std::string get_string ()
350  {
351  size_t len = get_int<size_t>();
352  return get_raw_string(len);
353  }
354 
355  // TODO maybe trailing return types is a solution to make this work without having to specify the template parameters? (also for the othter, similar methods in this class)
360  template<typename T>
362  {
363  T res;
364  get_raw( (char*)(&res), sizeof(T) );
365  return res;
366  }
367 
372  template<typename T>
373  void get_plain (T& res)
374  {
375  get_raw( (char*)(&res), sizeof(T) );
376  }
377 
381  template<typename T>
382  T get_int ()
383  {
384  return get_plain<T>();
385  }
386 
390  template<typename T>
391  void get_int (T& res)
392  {
393  res = get_plain<T>();
394  }
395 
399  template<typename T>
401  {
402  return get_plain<T>();
403  }
404 
408  template<typename T>
409  void get_float (T& res)
410  {
411  res = get_plain<T>();
412  }
413 
414  // -------------------------------------------------------------------------
415  // Data Members
416  // -------------------------------------------------------------------------
417 
418 private:
419 
420  InputBuffer buffer_;
421 
422 };
423 
424 } // namespace utils
425 } // namespace genesis
426 
427 #endif // include guard
T get_plain()
Read as many bytes from the stream as the type T holds, and return them in form of a value of type T...
void get_float(T &res)
Read an floating point number from the stream and store it in the result.
void put_plain(const T v)
Write plain data to the stream, by casting it to a char array.
Serializer(std::ostream &outstream)
Deserializer(std::string const &file_name)
void file_output_stream(std::string const &filename, std::ofstream &out_stream, std::ios_base::openmode mode=std::ios_base::out)
Helper function to obtain an output stream to a file.
void put_null(const size_t n)
Write n zero bytes (\0) to the stream.
Input source for reading byte data from a file.
std::string get_string()
Read a string from the stream, provided that its length it written preceding it, as done by put_strin...
void put_raw_string(const std::string &v)
Write raw data, provided as a string, to the stream, without writing its length.
std::string to_string(T const &v)
Return a string representation of a given value.
Definition: string.hpp:300
void get_int(T &res)
Read an integer number from the stream and store it in the result.
Provides some valuable additions to STD.
void put_raw(char const *data, size_t n)
Write raw data, provided as a char array of length n, to the stream.
void put_float(const T v)
Write a floating point number to the stream.
std::string get_raw_string(size_t n)
Read n bytes from the stream and return them as a string.
std::unique_ptr< T > make_unique(Args &&...args)
Returns a std::unique_ptr for a given type.
Definition: std.hpp:68
void put_string(const std::string &v)
Write a string, preceded by its length, to the stream. Use get_string() to read it.
Deserializer(std::istream &instream)
bool get_null(size_t n)
Reads n bytes from the stream and returns whether all of them are \0 bytes.
Serializer(const std::string &filename)
void put_int(const T v)
Write an integer number to the stream.
void get_plain(T &res)
Read as many bytes from the stream as the type T holds, and put them in the result value of type T...
void get_raw(char *buffer, size_t n)
Read n bytes from the stream and store them in the buffer.
T get_int()
Read an integer number from the stream and return it.
size_t read(char *target, size_t size)
T get_float()
Read a floating point number from the stream and return it.
Input source for reading byte data from an istream.