Orocos Real-Time Toolkit  2.9.0
binary_data_archive.hpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: Peter Soetens Thu Oct 22 11:59:08 CEST 2009 binary_data_archive.hpp
3 
4  binary_data_archive.hpp - description
5  -------------------
6  begin : Thu October 22 2009
7  copyright : (C) 2009 Peter Soetens
8  email : peter@thesourcworks.com
9 
10  ***************************************************************************
11  * This library is free software; you can redistribute it and/or *
12  * modify it under the terms of the GNU General Public *
13  * License as published by the Free Software Foundation; *
14  * version 2 of the License. *
15  * *
16  * As a special exception, you may use this file as part of a free *
17  * software library without restriction. Specifically, if other files *
18  * instantiate templates or use macros or inline functions from this *
19  * file, or you compile this file and link it with other files to *
20  * produce an executable, this file does not by itself cause the *
21  * resulting executable to be covered by the GNU General Public *
22  * License. This exception does not however invalidate any other *
23  * reasons why the executable file might be covered by the GNU General *
24  * Public License. *
25  * *
26  * This library is distributed in the hope that it will be useful, *
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
29  * Lesser General Public License for more details. *
30  * *
31  * You should have received a copy of the GNU General Public *
32  * License along with this library; if not, write to the Free Software *
33  * Foundation, Inc., 59 Temple Place, *
34  * Suite 330, Boston, MA 02111-1307 USA *
35  * *
36  ***************************************************************************/
37 
38 
39 
40 
41 #ifndef BINARY_DATA_ARCHIVE_HPP_
42 #define BINARY_DATA_ARCHIVE_HPP_
43 
44 // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
45 // (C) Copyright 2009 Peter Soetens - http://www.thesourceworks.com .
46 // Use, modification and distribution is subject to the Boost Software
47 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
48 // http://www.boost.org/LICENSE_1_0.txt)
49 
50 // See http://www.boost.org for updates, documentation, and revision history.
51 
52 
68 #include <cassert>
69 #include <istream>
70 #include <ostream>
71 #include <streambuf>
72 #include <cstring>
73 #include <boost/version.hpp>
74 #include <boost/serialization/serialization.hpp>
75 #include <boost/serialization/is_bitwise_serializable.hpp>
76 #include <boost/archive/detail/iserializer.hpp>
77 #include <boost/archive/detail/oserializer.hpp>
78 #include <boost/archive/archive_exception.hpp>
79 #include <boost/config.hpp>
80 #include <boost/mpl/bool.hpp>
81 
82 // binary_data_archive API changed at 1.42, 1.46
83 #include <boost/version.hpp>
84 #if BOOST_VERSION >= 104600
85 #include <boost/serialization/item_version_type.hpp>
86 #endif
87 
88 #ifndef BOOST_PFTO
89 //Partial Function Template Ordering removed from boost in 1.59, setting it to nothing seems to work
90 //(was also done in <boost/ptfo.hpp> itself, header removed from 1.59)
91 //and keeps its functionality for older boost versions
92 #define BOOST_PFTO
93 #endif
94 
95 namespace RTT
96 {
97  namespace mqueue
98  {
99 
107  {
108  std::streambuf& m_sb;
109  int data_read;
110  public:
111  typedef char Elem;
113 
117  typedef boost::mpl::bool_<true> is_loading;
121  typedef boost::mpl::bool_<false> is_saving;
122 
127  binary_data_iarchive(std::streambuf& bsb) :
128  m_sb(bsb), data_read(0)
129  {
130  }
131 
136  binary_data_iarchive(std::istream& is) :
137  m_sb(*is.rdbuf()), data_read(0)
138  {
139  }
140 
145  unsigned int get_library_version() { return 0; }
146 
152  void reset_object_address(const void * new_address, const void * old_address) {}
153 
158 
164  template<class T>
165  const boost::archive::detail::basic_pointer_iserializer *
166  register_type(T * = NULL) {return 0;}
167 
175  void *t,
176  const /* BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) */ boost::archive::detail::basic_iserializer & bis
177  ) {
178  assert(false);
179  }
180 
185  template<class T>
186  void load_override(T & t, BOOST_PFTO int){
187  load_a_type(t, boost::mpl::bool_<boost::serialization::implementation_level<T>::value == boost::serialization::primitive_type>() );
188  //archive::load(* this->This(), t);
189  }
190 
196 #if 0
197  void load_override(const boost::serialization::nvp<boost::serialization::collection_size_type> & t, int){
198  size_t x=0;
199  * this >> x;
200  t.value() = boost::serialization::collection_size_type(x);
201  }
202 #endif
203  template<class T>
204  void load_override(const boost::serialization::nvp<T> & t, int){
205  T& x(t.value());
206  * this >> x;
207  }
208 
214  template<class T>
215 #if BOOST_VERSION >= 106100
216  void load_override(const boost::serialization::array_wrapper<T> &t, int)
217  {
218  boost::serialization::array_wrapper<T> tmp(t.address(), t.count());
219 #else
220  void load_override(const boost::serialization::array<T> &t, int)
221  {
222  boost::serialization::array<T> tmp(t.address(), t.count());
223 #endif
224  *this >> tmp;
225  }
226 
232  template<class T>
234  this->load_override(t, 0);
235  return * this;
236  }
237 
243  template<class T>
245  return this->operator>>(t);
246  }
247 
253  void load_binary(void *address, std::size_t count)
254  {
255  // note: an optimizer should eliminate the following for char files
256  std::streamsize s = count / sizeof(Elem);
257  std::streamsize scount = m_sb.sgetn(
258  static_cast<Elem *> (address), s);
259  if (scount != static_cast<std::streamsize> (s))
260 #if BOOST_VERSION >= 104400
261  boost::serialization::throw_exception(
262  boost::archive::archive_exception(
263  boost::archive::archive_exception::input_stream_error));
264 #else
265  boost::serialization::throw_exception(
266  boost::archive::archive_exception(
267  boost::archive::archive_exception::stream_error));
268 #endif
269  // note: an optimizer should eliminate the following for char files
270  s = count % sizeof(Elem);
271  if (0 < s)
272  {
273  // if(is.fail())
274  // boost::serialization::throw_exception(
275  // archive_exception(archive_exception::stream_error)
276  // );
277  Elem t;
278  scount = m_sb.sgetn(&t, 1);
279  if (scount != 1)
280 #if BOOST_VERSION >= 104400
281  boost::serialization::throw_exception(
282  boost::archive::archive_exception(
283  boost::archive::archive_exception::input_stream_error));
284 #else
285  boost::serialization::throw_exception(
286  boost::archive::archive_exception(
287  boost::archive::archive_exception::stream_error));
288 #endif
289  std::memcpy(static_cast<char*> (address) + (count - s), &t,
290  s);
291  }
292  data_read += count;
293  }
294 
300  template<class T>
301  binary_data_iarchive &load_a_type(T &t,boost::mpl::true_){
302  load_binary(&t, sizeof(T));
303  return *this;
304  }
305 
311  template<class T>
312  binary_data_iarchive &load_a_type(T &t,boost::mpl::false_){
313 #if BOOST_VERSION >= 104100
314  boost::archive::detail::load_non_pointer_type<binary_data_iarchive>::load_only::invoke(*this,t);
315 #else
316  boost::archive::detail::load_non_pointer_type<binary_data_iarchive,T>::load_only::invoke(*this,t);
317 #endif
318  return *this;
319  }
320 
326  template <class T>
327  #if defined(BOOST_NO_DEPENDENT_NESTED_DERIVATIONS)
328  struct apply {
329  typedef BOOST_DEDUCED_TYPENAME boost::serialization::is_bitwise_serializable<T>::type type;
330  };
331  #else
332  struct apply : public boost::serialization::is_bitwise_serializable<T> {};
333  #endif
334  };
335 
339  template<class ValueType>
340 #if BOOST_VERSION >= 106100
341  void load_array(boost::serialization::array_wrapper<ValueType>& a,
342 #else
343  void load_array(boost::serialization::array<ValueType>& a,
344 #endif
345  unsigned int)
346  {
347  load_binary(a.address(), a.count()
348  * sizeof(ValueType));
349  }
350 
354  int getArchiveSize() { return data_read; }
355  };
356 
363  {
364  std::streambuf & m_sb;
365  int data_written;
366  bool mdo_save;
367  public:
368  typedef char Elem;
372  typedef boost::mpl::bool_<false> is_loading;
376  typedef boost::mpl::bool_<true> is_saving;
377 
386  binary_data_oarchive(std::ostream& os,bool do_save = true) :
387  m_sb(*os.rdbuf()), data_written(0), mdo_save(do_save)
388  {
389  }
390 
399  binary_data_oarchive(std::streambuf& sb,bool do_save = true) :
400  m_sb(sb), data_written(0), mdo_save(do_save)
401  {
402  }
403 
408  unsigned int get_library_version() { return 0; }
409 
415  template<class T>
416  const boost::archive::detail::basic_pointer_iserializer *
417  register_type(T * = NULL) {return 0;}
418 
425  const void *x,
426  const boost::archive::detail::basic_oserializer & bos
427  ) {
428  assert(false);
429  //(bos.save_object_data)(*this, x);
430  }
431 
437  template<class T>
439  return save_a_type(t,boost::mpl::bool_< boost::serialization::implementation_level<T>::value == boost::serialization::primitive_type>() );
440  }
441 
447  template<class T>
449  return this->operator<<(t);
450  }
451 
457  inline void save_binary(const void *address, std::size_t count)
458  {
459  // figure number of elements to output - round up
460  count = (count + sizeof(Elem) - 1) / sizeof(Elem);
461  if (mdo_save) {
462  std::streamsize scount = m_sb.sputn(
463  static_cast<const Elem *> (address), count);
464  if (count != static_cast<std::size_t> (scount))
465 #if BOOST_VERSION >= 104400
466  boost::serialization::throw_exception(
467  boost::archive::archive_exception(
468  boost::archive::archive_exception::output_stream_error));
469 #else
470  boost::serialization::throw_exception(
471  boost::archive::archive_exception(
472  boost::archive::archive_exception::stream_error));
473 #endif
474  }
475  data_written += count;
476  }
477 
483  template<class T>
484  binary_data_oarchive &save_a_type(T const &t,boost::mpl::true_){
485  save_binary(&t, sizeof(T));
486  return *this;
487  }
488 
489 #if BOOST_VERSION >= 104600
490  binary_data_oarchive &save_a_type(const boost::serialization::version_type & t,boost::mpl::true_){
491  // ignored, the load function is never called, so we don't store it.
492  return *this;
493  }
494  binary_data_oarchive &save_a_type(const boost::serialization::item_version_type & t,boost::mpl::true_){
495  // ignored, the load function is never called, so we don't store it.
496  return *this;
497  }
498 #endif
499 
505  template<class T>
506  binary_data_oarchive &save_a_type(T const &t,boost::mpl::false_){
507 #if BOOST_VERSION >= 104100
508  boost::archive::detail::save_non_pointer_type<binary_data_oarchive>::save_only::invoke(*this,t);
509 #else
510  boost::archive::detail::save_non_pointer_type<binary_data_oarchive,T>::save_only::invoke(*this,t);
511 #endif
512  return *this;
513  }
514 
520  template <class T>
521  #if defined(BOOST_NO_DEPENDENT_NESTED_DERIVATIONS)
522  struct apply {
523  typedef BOOST_DEDUCED_TYPENAME boost::serialization::is_bitwise_serializable<T>::type type;
524  };
525  #else
526  struct apply : public boost::serialization::is_bitwise_serializable<T> {};
527  #endif
528  };
529 
533  template<class ValueType>
534 #if BOOST_VERSION >= 106100
535  void save_array(boost::serialization::array_wrapper<ValueType> const& a,
536 #else
537  void save_array(boost::serialization::array<ValueType> const& a,
538 #endif
539  unsigned int)
540  {
541  save_binary(a.address(), a.count()
542  * sizeof(ValueType));
543  }
544 
548  int getArchiveSize() { return data_written; }
549  };
550  }
551 }
552 
553 BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(RTT::mqueue::binary_data_oarchive)
554 BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(RTT::mqueue::binary_data_iarchive)
555 
556 #endif /* BINARY_DATA_ARCHIVE_HPP_ */
This archive is capable of saving objects of serialization level 1 and 2 in a binary, non-portable format.
void save_array(boost::serialization::array< ValueType > const &a, unsigned int)
The optimized save_array dispatches to save_binary.
binary_data_iarchive & load_a_type(T &t, boost::mpl::false_)
Specialisation for writing out composite types (objects).
binary_data_oarchive & operator&(T const &t)
Saving Archive Concept::operator&.
#define BOOST_PFTO
boost::mpl::bool_< true > is_saving
Saving Archive Concept::is_saving.
binary_data_oarchive & save_a_type(T const &t, boost::mpl::false_)
Specialisation for writing out composite types (objects).
boost::mpl::bool_< false > is_loading
Saving Archive Concept::is_loading.
This archive is capable of loading objects of serialization level 1 and 2 from a binary, non-portable format.
unsigned int get_library_version()
Saving Archive Concept::get_library_version()
void load_array(boost::serialization::array< ValueType > &a, unsigned int)
The optimized save_array dispatches to save_binary.
binary_data_oarchive(std::ostream &os, bool do_save=true)
Constructor from a standard output stream.
int getArchiveSize()
Helper method to say how much we read.
void load_override(const boost::serialization::nvp< T > &t, int)
These load_override functions are required to handle the nvt<T> cases in the serialization code...
const boost::archive::detail::basic_pointer_iserializer * register_type(T *=NULL)
Loading Archive Concept::register_type<T>() and ::register_type(u)
binary_data_iarchive(std::streambuf &bsb)
Constructor from a standard output stream.
binary_data_iarchive & operator&(T &t)
Loading Archive Concept::operator&.
unsigned int get_library_version()
Loading Archive Concept::get_library_version()
binary_data_iarchive & operator>>(T &t)
Loading Archive Concept::operator>>
binary_data_iarchive & load_a_type(T &t, boost::mpl::true_)
Specialisation for writing out primitive types.
binary_data_oarchive(std::streambuf &sb, bool do_save=true)
Constructor from a standard stream buffer.
binary_data_oarchive & save_a_type(T const &t, boost::mpl::true_)
Specialisation for writing out primitive types.
int getArchiveSize()
Helper method to say how much we wrote.
void delete_created_pointers()
Loading Archive Concept::delete_created_pointers()
void load_override(const boost::serialization::array< T > &t, int)
Specialisation that covers a boost serialization array created with make_array()
std::ostream & operator<<(std::ostream &os, const BufferPolicy &bp)
boost::mpl::bool_< true > is_loading
Loading Archive Concept::is_loading.
We provide an optimized load for all fundamental types typedef serialization::is_bitwise_serializable...
void reset_object_address(const void *new_address, const void *old_address)
Loading Archive Concept::reset_object_address(v,u)
void load_object(void *t, const boost::archive::detail::basic_iserializer &bis)
Note: not in LoadArchive concept but required when we use archive::load ! This function is only used ...
void save_binary(const void *address, std::size_t count)
Saving Archive Concept::save_binary(u, count)
boost::mpl::bool_< false > is_saving
Loading Archive Concept::is_saving.
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:52
binary_data_iarchive(std::istream &is)
Constructor from a standard stream buffer.
const boost::archive::detail::basic_pointer_iserializer * register_type(T *=NULL)
Saving Archive Concept::register_type<T>() and ::register_type(u)
void save_object(const void *x, const boost::archive::detail::basic_oserializer &bos)
Note: not in LoadArchive concept but required when we use archive::save !
void load_override(T &t, BOOST_PFTO int)
The standard type loading function.
binary_data_oarchive & operator<<(T const &t)
Saving Archive Concept::operator<<.
void load_binary(void *address, std::size_t count)
Loading Archive Concept::load_binary(u, count)
We provide an optimized load for all fundamental types typedef serialization::is_bitwise_serializable...