Orocos Real-Time Toolkit  2.8.3
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 #if BOOST_VERSION >= 106400
75 // The class name has been changed from boost::serialization::array<T> to array_wrapper<T> in Boost 1.61,
76 // but the header has only be renamed in Boost 1.64. Starting from Boost 1.65 array.hpp includes array_wrapper.hpp,
77 // but with 1.64 compilation fails if array_wrapper.hpp is not included.
78 # include <boost/serialization/array_wrapper.hpp>
79 #else
80 # include <boost/serialization/array.hpp>
81 #endif
82 #include <boost/serialization/serialization.hpp>
83 #include <boost/serialization/is_bitwise_serializable.hpp>
84 #include <boost/archive/detail/iserializer.hpp>
85 #include <boost/archive/detail/oserializer.hpp>
86 #include <boost/archive/archive_exception.hpp>
87 #include <boost/config.hpp>
88 #include <boost/mpl/bool.hpp>
89 
90 // binary_data_archive API changed at 1.42, 1.46
91 #include <boost/version.hpp>
92 #if BOOST_VERSION >= 104600
93 #include <boost/serialization/item_version_type.hpp>
94 #endif
95 
96 #ifndef BOOST_PFTO
97 //Partial Function Template Ordering removed from boost in 1.59, setting it to nothing seems to work
98 //(was also done in <boost/ptfo.hpp> itself, header removed from 1.59)
99 //and keeps its functionality for older boost versions
100 #define BOOST_PFTO
101 #endif
102 
103 namespace RTT
104 {
105  namespace mqueue
106  {
107 
115  {
116  std::streambuf& m_sb;
117  int data_read;
118  public:
119  typedef char Elem;
121 
125  typedef boost::mpl::bool_<true> is_loading;
129  typedef boost::mpl::bool_<false> is_saving;
130 
135  binary_data_iarchive(std::streambuf& bsb) :
136  m_sb(bsb), data_read(0)
137  {
138  }
139 
144  binary_data_iarchive(std::istream& is) :
145  m_sb(*is.rdbuf()), data_read(0)
146  {
147  }
148 
153  unsigned int get_library_version() { return 0; }
154 
160  void reset_object_address(const void * new_address, const void * old_address) {}
161 
166 
172  template<class T>
173  const boost::archive::detail::basic_pointer_iserializer *
174  register_type(T * = NULL) {return 0;}
175 
183  void *t,
184  const /* BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) */ boost::archive::detail::basic_iserializer & bis
185  ) {
186  assert(false);
187  }
188 
193  template<class T>
194  void load_override(T & t, BOOST_PFTO int){
195  load_a_type(t, boost::mpl::bool_<boost::serialization::implementation_level<T>::value == boost::serialization::primitive_type>() );
196  //archive::load(* this->This(), t);
197  }
198 
204 #if 0
205  void load_override(const boost::serialization::nvp<boost::serialization::collection_size_type> & t, int){
206  size_t x=0;
207  * this >> x;
208  t.value() = boost::serialization::collection_size_type(x);
209  }
210 #endif
211  template<class T>
212  void load_override(const boost::serialization::nvp<T> & t, int){
213  T& x(t.value());
214  * this >> x;
215  }
216 
222  template<class T>
223 #if BOOST_VERSION >= 106100
224  void load_override(const boost::serialization::array_wrapper<T> &t, int)
225  {
226  boost::serialization::array_wrapper<T> tmp(t.address(), t.count());
227 #else
228  void load_override(const boost::serialization::array<T> &t, int)
229  {
230  boost::serialization::array<T> tmp(t.address(), t.count());
231 #endif
232  *this >> tmp;
233  }
234 
240  template<class T>
242  this->load_override(t, 0);
243  return * this;
244  }
245 
251  template<class T>
253  return this->operator>>(t);
254  }
255 
261  void load_binary(void *address, std::size_t count)
262  {
263  // note: an optimizer should eliminate the following for char files
264  std::streamsize s = count / sizeof(Elem);
265  std::streamsize scount = m_sb.sgetn(
266  static_cast<Elem *> (address), s);
267  if (scount != static_cast<std::streamsize> (s))
268 #if BOOST_VERSION >= 104400
269  boost::serialization::throw_exception(
270  boost::archive::archive_exception(
271  boost::archive::archive_exception::input_stream_error));
272 #else
273  boost::serialization::throw_exception(
274  boost::archive::archive_exception(
275  boost::archive::archive_exception::stream_error));
276 #endif
277  // note: an optimizer should eliminate the following for char files
278  s = count % sizeof(Elem);
279  if (0 < s)
280  {
281  // if(is.fail())
282  // boost::serialization::throw_exception(
283  // archive_exception(archive_exception::stream_error)
284  // );
285  Elem t;
286  scount = m_sb.sgetn(&t, 1);
287  if (scount != 1)
288 #if BOOST_VERSION >= 104400
289  boost::serialization::throw_exception(
290  boost::archive::archive_exception(
291  boost::archive::archive_exception::input_stream_error));
292 #else
293  boost::serialization::throw_exception(
294  boost::archive::archive_exception(
295  boost::archive::archive_exception::stream_error));
296 #endif
297  std::memcpy(static_cast<char*> (address) + (count - s), &t,
298  s);
299  }
300  data_read += count;
301  }
302 
308  template<class T>
309  binary_data_iarchive &load_a_type(T &t,boost::mpl::true_){
310  load_binary(&t, sizeof(T));
311  return *this;
312  }
313 
319  template<class T>
320  binary_data_iarchive &load_a_type(T &t,boost::mpl::false_){
321 #if BOOST_VERSION >= 104100
322  boost::archive::detail::load_non_pointer_type<binary_data_iarchive>::load_only::invoke(*this,t);
323 #else
324  boost::archive::detail::load_non_pointer_type<binary_data_iarchive,T>::load_only::invoke(*this,t);
325 #endif
326  return *this;
327  }
328 
334  template <class T>
335  #if defined(BOOST_NO_DEPENDENT_NESTED_DERIVATIONS)
336  struct apply {
337  typedef BOOST_DEDUCED_TYPENAME boost::serialization::is_bitwise_serializable<T>::type type;
338  };
339  #else
340  struct apply : public boost::serialization::is_bitwise_serializable<T> {};
341  #endif
342  };
343 
347  template<class ValueType>
348 #if BOOST_VERSION >= 106100
349  void load_array(boost::serialization::array_wrapper<ValueType>& a,
350 #else
351  void load_array(boost::serialization::array<ValueType>& a,
352 #endif
353  unsigned int)
354  {
355  load_binary(a.address(), a.count()
356  * sizeof(ValueType));
357  }
358 
362  int getArchiveSize() { return data_read; }
363  };
364 
371  {
372  std::streambuf & m_sb;
373  int data_written;
374  bool mdo_save;
375  public:
376  typedef char Elem;
380  typedef boost::mpl::bool_<false> is_loading;
384  typedef boost::mpl::bool_<true> is_saving;
385 
394  binary_data_oarchive(std::ostream& os,bool do_save = true) :
395  m_sb(*os.rdbuf()), data_written(0), mdo_save(do_save)
396  {
397  }
398 
407  binary_data_oarchive(std::streambuf& sb,bool do_save = true) :
408  m_sb(sb), data_written(0), mdo_save(do_save)
409  {
410  }
411 
416  unsigned int get_library_version() { return 0; }
417 
423  template<class T>
424  const boost::archive::detail::basic_pointer_iserializer *
425  register_type(T * = NULL) {return 0;}
426 
433  const void *x,
434  const boost::archive::detail::basic_oserializer & bos
435  ) {
436  assert(false);
437  //(bos.save_object_data)(*this, x);
438  }
439 
445  template<class T>
447  return save_a_type(t,boost::mpl::bool_< boost::serialization::implementation_level<T>::value == boost::serialization::primitive_type>() );
448  }
449 
455  template<class T>
457  return this->operator<<(t);
458  }
459 
465  inline void save_binary(const void *address, std::size_t count)
466  {
467  // figure number of elements to output - round up
468  count = (count + sizeof(Elem) - 1) / sizeof(Elem);
469  if (mdo_save) {
470  std::streamsize scount = m_sb.sputn(
471  static_cast<const Elem *> (address), count);
472  if (count != static_cast<std::size_t> (scount))
473 #if BOOST_VERSION >= 104400
474  boost::serialization::throw_exception(
475  boost::archive::archive_exception(
476  boost::archive::archive_exception::output_stream_error));
477 #else
478  boost::serialization::throw_exception(
479  boost::archive::archive_exception(
480  boost::archive::archive_exception::stream_error));
481 #endif
482  }
483  data_written += count;
484  }
485 
491  template<class T>
492  binary_data_oarchive &save_a_type(T const &t,boost::mpl::true_){
493  save_binary(&t, sizeof(T));
494  return *this;
495  }
496 
497 #if BOOST_VERSION >= 104600
498  binary_data_oarchive &save_a_type(const boost::serialization::version_type & t,boost::mpl::true_){
499  // ignored, the load function is never called, so we don't store it.
500  return *this;
501  }
502  binary_data_oarchive &save_a_type(const boost::serialization::item_version_type & t,boost::mpl::true_){
503  // ignored, the load function is never called, so we don't store it.
504  return *this;
505  }
506 #endif
507 
513  template<class T>
514  binary_data_oarchive &save_a_type(T const &t,boost::mpl::false_){
515 #if BOOST_VERSION >= 104100
516  boost::archive::detail::save_non_pointer_type<binary_data_oarchive>::save_only::invoke(*this,t);
517 #else
518  boost::archive::detail::save_non_pointer_type<binary_data_oarchive,T>::save_only::invoke(*this,t);
519 #endif
520  return *this;
521  }
522 
528  template <class T>
529  #if defined(BOOST_NO_DEPENDENT_NESTED_DERIVATIONS)
530  struct apply {
531  typedef BOOST_DEDUCED_TYPENAME boost::serialization::is_bitwise_serializable<T>::type type;
532  };
533  #else
534  struct apply : public boost::serialization::is_bitwise_serializable<T> {};
535  #endif
536  };
537 
541  template<class ValueType>
542 #if BOOST_VERSION >= 106100
543  void save_array(boost::serialization::array_wrapper<ValueType> const& a,
544 #else
545  void save_array(boost::serialization::array<ValueType> const& a,
546 #endif
547  unsigned int)
548  {
549  save_binary(a.address(), a.count()
550  * sizeof(ValueType));
551  }
552 
556  int getArchiveSize() { return data_written; }
557  };
558  }
559 }
560 
561 BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(RTT::mqueue::binary_data_oarchive)
562 BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(RTT::mqueue::binary_data_iarchive)
563 
564 #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&.
RTT_API std::ostream & operator<<(std::ostream &os, FlowStatus fs)
Definition: FlowStatus.cpp:45
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()
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:51
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...