CFEL - ASG Software Suite  2.5.0
CASS
serializer.hpp
Go to the documentation of this file.
1 //Copyright (C) 2010, 2015 Lutz Foucar
2 
3 /**
4  * @file cass/serializer.hpp file contains classes for serializing objects
5  *
6  * @author Lutz Foucar
7  */
8 
9 #ifndef _SERIALIZER_HPP_
10 #define _SERIALIZER_HPP_
11 
12 #include <sstream>
13 #include <fstream>
14 #include <string>
15 #include <stdexcept>
16 #include <typeinfo>
17 #include <cstring>
18 #include <iomanip>
19 #include <iostream>
20 
21 #include <stdint.h>
22 #include <zlib.h>
23 
24 /**
25  * @note if this is set, SerializerBackend is made abstract (pure virtual member)
26  * to see if it is instantiated somewhere.
27  * switch it off in release mode for performance gain.
28  * @author Stephan Kassemeyer
29  */
30 //#define SERIALIZER_INTERFACE_TEST
31 
32 namespace cass
33 {
34 
35 /** A serializer.
36  *
37  * base class that will serialize / de serialize
38  * Serializable classes to an iostream
39  * This is an interface that should not be instantiated
40  * (can be made pure virtual once virtual methods are introduced).
41  *
42  * @author Lutz Foucar
43  * @author Stephan Kassemeyer
44  */
46 {
47 public:
48  /** constructor */
52  {}
53 
54 #ifdef SERIALIZER_INTERFACE_TEST
55  /** virtual member to test */
56  virtual void abstractTest() = 0;
57 
58  /** virtual member to test */
59  virtual ~SerializerBackend(){}
60 #endif
61 
62  /** flush the stream */
63  void flush() { _stream->flush(); }
64 
65  /** write data to the stream
66  *
67  * @return reference to the out stream
68  * @param data the data to write
69  * @param n size of the data
70  */
71  std::ostream& writeToStream( const char* data, std::streamsize n)
72  {
74  return _stream->write(data, n);
75  }
76 
77  /** read data from the stream
78  *
79  * @return reference to the in stream
80  * @param data the data to write
81  * @param n size of the data
82  */
83  std::istream& readFromStream( char* data, std::streamsize n)
84  {
86  {
87  std::istream& stream = _stream->read(data, n);
88  addToInChecksum(data, n);
89  return(stream);
90  }
91  else
92  return _stream->read(data, n);
93  }
94 
95  //@{
96  /** control checksum calculation for the next values added
97  *
98  * usage:
99  * add...;
100  * add...;
101  * startChecksumGroupforRead();
102  * add...;
103  * add...;
104  * if (!endChecksumGroupForRead()) error();
105  */
107  {
109  r_sum1 = 0xff;
110  r_sum2 = 0xff;
111  }
113  {
115  /** finalize checksum: */
116  r_sum1 = (r_sum1 & 0xff) + (r_sum1 >> 8);
117  r_sum2 = (r_sum2 & 0xff) + (r_sum2 >> 8);
118  if (retrieve<uint8_t>() != (uint8_t)r_sum1 ) return false;
119  if (retrieve<uint8_t>() != (uint8_t)r_sum2 ) return false;
120  return true;
121  }
122  //@}
123 
124  //@{
125  /** control checksum for writing to stream
126  *
127  * usage:
128  * retrieve...;
129  * retrieve...;
130  * startChecksumGroupforWrite();
131  * retrieve...;
132  * retrieve...;
133  * endChecksumGroupForWrite();
134  */
136  {
138  w_sum1 = 0xff;
139  w_sum2 = 0xff;
140  }
142  {
144  /** finalize checksum: */
145  w_sum1 = (w_sum1 & 0xff) + (w_sum1 >> 8);
146  w_sum2 = (w_sum2 & 0xff) + (w_sum2 >> 8);
147  add(static_cast<uint8_t>(w_sum1) );
148  add(static_cast<uint8_t>(w_sum2) );
149  }
150  //@}
151 
152  /** add arbitrary value to the stream
153  *
154  * @tparam Type the type of the value
155  * @param value the value to add
156  */
157  template <typename Type>
158  void add(const Type& value)
159  {
160  writeToStream(reinterpret_cast<const char *> (&value), sizeof (Type));
161  }
162 
163  /** read arbitrary value from stream
164  *
165  * @tparam Type the type of the value
166  * @return the read value
167  */
168  template <typename Type>
169  Type retrieve()
170  {
171  Type value;
172  readFromStream (reinterpret_cast<char *> (&value), sizeof (Type));
173  return value;
174  }
175 
176 protected:
177  /** fletcher16 algorithm for 8 bit input
178  *
179  * @param data the data to add to the fletcher algorithm
180  * @param len the size of the data to be added to the fletcher algorithm
181  *
182  * @author Stephan Kassemeyer
183  */
184  void addToOutChecksum( const char* data, std::streamsize len)
185  {
186  while (len) {
187  size_t tlen = len > 21 ? 21 : len;
188  len -= tlen;
189  do {
190  w_sum1 += *data++;
191  w_sum2 += w_sum1;
192  } while (--tlen);
193  w_sum1 = (w_sum1 & 0xff) + (w_sum1 >> 8);
194  w_sum2 = (w_sum2 & 0xff) + (w_sum2 >> 8);
195  }
196  }
197 
198  /** fletcher16 algorithm for 8 bit input
199  *
200  * @param data the data to add to the fletcher algorithm
201  * @param len the size of the data to be added to the fletcher algorithm
202  *
203  * @author Stephan Kassemeyer
204  */
205  void addToInChecksum( const char* data, std::streamsize len)
206  {
207  while (len) {
208  size_t tlen = len > 21 ? 21 : len;
209  len -= tlen;
210  do {
211  r_sum1 += *data++;
212  r_sum2 += r_sum1;
213  } while (--tlen);
214  r_sum1 = (r_sum1 & 0xff) + (r_sum1 >> 8);
215  r_sum2 = (r_sum2 & 0xff) + (r_sum2 >> 8);
216  }
217  }
218 
219 protected:
220  /** the string to serialize the objects to (buffer) */
221  std::iostream* _stream;
222 
223  /** sum 1 for reading */
224  uint16_t r_sum1;
225 
226  /** sum 2 for reading */
227  uint16_t r_sum2;
228 
229  /** sum 1 for writing */
230  uint16_t w_sum1;
231 
232  /** sum 2 for writing */
233  uint16_t w_sum2;
234 
235  /** flag to enable getting parts to a checksum */
237 
238  /** flag to enable adding parts to a checksum */
240 
241 };
242 /** specialization for strings
243  *
244  * write the length of the string, then the string itselve
245  *
246  * @param string to add to the stream
247  */
248 template <>
249 inline
250 void SerializerBackend::add<std::string>(const std::string &str)
251 {
252  const size_t len(str.length());
253  add(len);
254  writeToStream(str.data(), len);
255 }
256 
257 /** specialization for string
258  *
259  * create a temp string with right size containing blanks and read data to it
260  *
261  * @return the retrieved string
262  */
263 template <>
264 inline
265 std::string SerializerBackend::retrieve<std::string>()
266 {
267  const size_t len(retrieve<size_t>());
268  std::string str(len,' ');
269  readFromStream (&str[0], len);
270  return str;
271 }
272 
273 
274 
275 
276 /** A string serializer.
277  *
278  * class that will serialize / de serialize Serializable classes to
279  * a stringstream
280  *
281  * The resulting buffer will be compressed and the string to be read from will
282  * be decompressed before reading from it
283  *
284  * @author Lutz Foucar
285  * @author Stephan Kassemeyer
286  */
288 {
289 public:
290  /** constructor.
291  *
292  * will open the stream in binary writing mode
293  *
294  * @param compressionlevel the level for the z-lib compression. Default is
295  * best compression
296  */
297  explicit Serializer(int compressionlevel = Z_BEST_COMPRESSION)
298  : _compresslevel(compressionlevel)
299  {
300  _stream = new std::stringstream(std::ios_base::binary|std::ios_base::out);
301  }
302 
303  /** constructor
304  *
305  * will open the provided string for reading in binary mode after it is
306  * decompressed
307  *
308  * @param string the compressed string that we want to read from
309  */
310  Serializer(const std::string &string)
311  {
312  _stream = new std::stringstream(decompress(string),
313  std::ios_base::binary|std::ios_base::in);
314  }
315 
316  /** destructor.
317  *
318  * deletes stream object
319  */
321  {
322  delete _stream;
323  }
324 
325  /** retrieve a const reference to the compressed string.
326  *
327  * @return const string of our stringstream
328  */
329  const std::string buffer()const
330  {
331  return compress(dynamic_cast<std::stringstream*>(_stream)->str());
332  }
333 
334 private:
335  /** Compress a STL string using zlib with given compression level and return
336  * the binary data.
337  *
338  * Copyright 2007 Timo Bingmann <tb@panthema.net>
339  * Distributed under the Boost Software License, Version 1.0.
340  * (See http://www.boost.org/LICENSE_1_0.txt)
341  *
342  * @return a compressed string
343  * @param str
344  */
345  std::string compress(const std::string& str) const
346  {
347  /** z_stream is zlib's control structure */
348  z_stream zs;
349  memset(&zs, 0, sizeof(zs));
350 
351  if (deflateInit(&zs, _compresslevel) != Z_OK)
352  throw(std::runtime_error("Serialzer::compress(): deflateInit failed"));
353 
354  zs.next_in = (Bytef*)str.data();
355  /** set the z_stream's input */
356  zs.avail_in = str.size();
357 
358  int ret;
359  char outbuffer[32768];
360  std::string outstring;
361 
362  /** retrieve the compressed bytes blockwise */
363  do {
364  zs.next_out = reinterpret_cast<Bytef*>(outbuffer);
365  zs.avail_out = sizeof(outbuffer);
366 
367  ret = deflate(&zs, Z_FINISH);
368 
369  if (outstring.size() < zs.total_out)
370  {
371  /** append the block to the output string */
372  outstring.append(outbuffer,
373  zs.total_out - outstring.size());
374  }
375  } while (ret == Z_OK);
376 
377  deflateEnd(&zs);
378 
379  /** an error occurred that was not EOF */
380  if (ret != Z_STREAM_END)
381  {
382  std::ostringstream oss;
383  oss << "Serialzier::compress(): Error during zlib compression. ErrorCode: ";
384  oss << ret << " (" << zs.msg << ")";
385  throw(std::runtime_error(oss.str()));
386  }
387 // std::ostringstream oss;
388 // oss << "Deflated data: "
389 // << str.size() << " -> " << outstring.size()
390 // << " (" << std::setprecision(1) << std::fixed
391 // << ( (1.0 - (float)outstring.size() / (float)str.size()) * 100.0)
392 // << "% or a factor of "
393 // << ((float)str.size() / (float)outstring.size())
394 // << " saved)."
395 // << std::endl;
396 // std::cout << oss.str();
397  return outstring;
398  }
399 
400  /** Decompress an STL string using zlib and return the inflated data.
401  *
402  * Copyright 2007 Timo Bingmann <tb@panthema.net>
403  * Distributed under the Boost Software License, Version 1.0.
404  * (See http://www.boost.org/LICENSE_1_0.txt)
405  *
406  * @return the de-ccompressed string
407  * @param str the compressed string
408  */
409  std::string decompress(const std::string& str) const
410  {
411  /** z_stream is zlib's control structure */
412  z_stream zs;
413  memset(&zs, 0, sizeof(zs));
414 
415  if (inflateInit(&zs) != Z_OK)
416  throw(std::runtime_error("Serializer::decompress(): inflateInit failed."));
417 
418  zs.next_in = (Bytef*)str.data();
419  zs.avail_in = str.size();
420 
421  int ret;
422  char outbuffer[32768];
423  std::string outstring;
424 
425  /** get the decompressed bytes blockwise using repeated calls to inflate */
426  do {
427  zs.next_out = reinterpret_cast<Bytef*>(outbuffer);
428  zs.avail_out = sizeof(outbuffer);
429 
430  ret = inflate(&zs, 0);
431 
432  if (outstring.size() < zs.total_out)
433  {
434  outstring.append(outbuffer, zs.total_out - outstring.size());
435  }
436 
437  } while (ret == Z_OK);
438 
439  inflateEnd(&zs);
440 
441  /** an error occurred that was not EOF */
442  if (ret != Z_STREAM_END)
443  {
444  std::ostringstream oss;
445  oss << "Serializer::decompress(): Error during zlib decompression: Error Code:";
446  oss << ret << " (" << zs.msg << ")";
447  throw(std::runtime_error(oss.str()));
448  }
449 // std::ostringstream oss;
450 // oss << "Inflated data: "
451 // << str.size() << " -> " << outstring.size()
452 // << " (" << std::setprecision(1) << std::fixed
453 // << ( ((float)str.size() / (float)outstring.size() - 1.0) * 100.0 )
454 // << "% or a factor of "
455 // << ((float)outstring.size() / (float)str.size())
456 // << " increase)."
457 // << std::endl;
458 // std::cout << oss.str();
459  return outstring;
460  }
461 
462 private:
464 
465 #ifdef SERIALIZER_INTERFACE_TEST
466  /** the abstract class test */
467  virtual void abstractTest() {}
468 #endif
469 };
470 
471 
472 
473 
474 
475 /** A file output serializer.
476  *
477  * class that will serialize Serializable classes to a file
478  *
479  * @author Stephan Kassemeyer
480  */
482 {
483 public:
484  /** constructor.
485  *
486  * will open the stream in binary reading/writing mode
487  */
488  SerializerWriteFile( const char* filename )
489  {
490  _stream = new std::fstream(filename, std::ios_base::binary|std::ios_base::out);
491  _opened = true;
492  }
493 
494  /** destructor.
495  *
496  * closes the file and deletes stream object.
497  */
499  {
500  close();
501  delete _stream;
502  }
503 
504  /** close file */
505  void close() {if (_opened) dynamic_cast<std::fstream*>(_stream)->close();}
506 
507 #ifdef SERIALIZER_INTERFACE_TEST
508  /** abstract class test */
509  virtual void abstractTest() {}
510 #endif
511 
512 protected:
513  /** flag to see if the file is opened */
514  bool _opened;
515 };
516 
517 
518 
519 
520 
521 /** A file input deserializer.
522  *
523  * class that will deserialize Serializable classes from a file
524  *
525  * @author Stephan Kassemeyer
526  */
528 {
529 public:
530  /** constructor.
531  *
532  * will open the stream in binary reading/writing mode
533  */
534  SerializerReadFile( const char* filename )
535  {
536  _stream = new std::fstream(filename, std::ios_base::binary|std::ios_base::in);
537  _opened = true;
538  }
539 
540  /** destructor.
541  *
542  * closes the file and deletes stream object.
543  */
545  {
546  close();
547  delete _stream;
548  }
549 
550  /** close file */
551  void close() {if (_opened) dynamic_cast<std::fstream*>(_stream)->close();}
552 
553 #ifdef SERIALIZER_INTERFACE_TEST
554  /** abstract class test */
555  virtual void abstractTest() {}
556 #endif
557 
558 protected:
559  /** flag to tell whether the file is opened */
560  bool _opened;
561 };
562 }//end namespace cass
563 #endif
SerializerBackend()
constructor
Definition: serializer.hpp:49
bool _opened
flag to see if the file is opened
Definition: serializer.hpp:514
~Serializer()
destructor.
Definition: serializer.hpp:320
void flush()
flush the stream
Definition: serializer.hpp:63
A file output serializer.
Definition: serializer.hpp:481
void startChecksumGroupForWrite()
control checksum for writing to stream
Definition: serializer.hpp:135
std::string decompress(const std::string &str) const
Decompress an STL string using zlib and return the inflated data.
Definition: serializer.hpp:409
void close()
close file
Definition: serializer.hpp:551
bool _opened
flag to tell whether the file is opened
Definition: serializer.hpp:560
bool _checkSumGroupStartedForWrite
flag to enable adding parts to a checksum
Definition: serializer.hpp:239
std::iostream * _stream
the string to serialize the objects to (buffer)
Definition: serializer.hpp:221
void close()
close file
Definition: serializer.hpp:505
void addToInChecksum(const char *data, std::streamsize len)
fletcher16 algorithm for 8 bit input
Definition: serializer.hpp:205
~SerializerWriteFile()
destructor.
Definition: serializer.hpp:498
A string serializer.
Definition: serializer.hpp:287
uint16_t w_sum2
sum 2 for writing
Definition: serializer.hpp:233
~SerializerReadFile()
destructor.
Definition: serializer.hpp:544
A file input deserializer.
Definition: serializer.hpp:527
const std::string buffer() const
retrieve a const reference to the compressed string.
Definition: serializer.hpp:329
void startChecksumGroupForRead()
control checksum calculation for the next values added
Definition: serializer.hpp:106
std::ostream & writeToStream(const char *data, std::streamsize n)
write data to the stream
Definition: serializer.hpp:71
void addToOutChecksum(const char *data, std::streamsize len)
fletcher16 algorithm for 8 bit input
Definition: serializer.hpp:184
uint16_t w_sum1
sum 1 for writing
Definition: serializer.hpp:230
Serializer(const std::string &string)
constructor
Definition: serializer.hpp:310
auxiliary data[Processor]
std::istream & readFromStream(char *data, std::streamsize n)
read data from the stream
Definition: serializer.hpp:83
std::string compress(const std::string &str) const
Compress a STL string using zlib with given compression level and return the binary data...
Definition: serializer.hpp:345
uint16_t r_sum2
sum 2 for reading
Definition: serializer.hpp:227
SerializerWriteFile(const char *filename)
constructor.
Definition: serializer.hpp:488
Type retrieve()
read arbitrary value from stream
Definition: serializer.hpp:169
Serializer(int compressionlevel=Z_BEST_COMPRESSION)
constructor.
Definition: serializer.hpp:297
uint16_t r_sum1
sum 1 for reading
Definition: serializer.hpp:224
check if there is some light in the chamber based upon the GMD value
void add(const Type &value)
add arbitrary value to the stream
Definition: serializer.hpp:158
bool _checkSumGroupStartedForRead
flag to enable getting parts to a checksum
Definition: serializer.hpp:236
SerializerReadFile(const char *filename)
constructor.
Definition: serializer.hpp:534