Orocos Real-Time Toolkit  2.5.0
binary_data_archive.hpp
Go to the documentation of this file.
00001 /***************************************************************************
00002   tag: Peter Soetens  Thu Oct 22 11:59:08 CEST 2009  binary_data_archive.hpp
00003 
00004                         binary_data_archive.hpp -  description
00005                            -------------------
00006     begin                : Thu October 22 2009
00007     copyright            : (C) 2009 Peter Soetens
00008     email                : peter@thesourcworks.com
00009 
00010  ***************************************************************************
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU General Public                   *
00013  *   License as published by the Free Software Foundation;                 *
00014  *   version 2 of the License.                                             *
00015  *                                                                         *
00016  *   As a special exception, you may use this file as part of a free       *
00017  *   software library without restriction.  Specifically, if other files   *
00018  *   instantiate templates or use macros or inline functions from this     *
00019  *   file, or you compile this file and link it with other files to        *
00020  *   produce an executable, this file does not by itself cause the         *
00021  *   resulting executable to be covered by the GNU General Public          *
00022  *   License.  This exception does not however invalidate any other        *
00023  *   reasons why the executable file might be covered by the GNU General   *
00024  *   Public License.                                                       *
00025  *                                                                         *
00026  *   This library is distributed in the hope that it will be useful,       *
00027  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00028  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00029  *   Lesser General Public License for more details.                       *
00030  *                                                                         *
00031  *   You should have received a copy of the GNU General Public             *
00032  *   License along with this library; if not, write to the Free Software   *
00033  *   Foundation, Inc., 59 Temple Place,                                    *
00034  *   Suite 330, Boston, MA  02111-1307  USA                                *
00035  *                                                                         *
00036  ***************************************************************************/
00037 
00038 
00039 
00040 
00041 #ifndef BINARY_DATA_ARCHIVE_HPP_
00042 #define BINARY_DATA_ARCHIVE_HPP_
00043 
00044 // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
00045 // (C) Copyright 2009 Peter Soetens - http://www.thesourceworks.com .
00046 // Use, modification and distribution is subject to the Boost Software
00047 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
00048 // http://www.boost.org/LICENSE_1_0.txt)
00049 
00050 //  See http://www.boost.org for updates, documentation, and revision history.
00051 
00052 
00068 #include <cassert>
00069 #include <istream>
00070 #include <ostream>
00071 #include <streambuf>
00072 #include <cstring>
00073 #include <boost/serialization/serialization.hpp>
00074 #include <boost/serialization/is_bitwise_serializable.hpp>
00075 #include <boost/archive/detail/iserializer.hpp>
00076 #include <boost/archive/detail/oserializer.hpp>
00077 #include <boost/archive/archive_exception.hpp>
00078 #include <boost/config.hpp>
00079 #include <boost/mpl/bool.hpp>
00080 
00081 // binary_data_archive API changed at 1.42, 1.46
00082 #include <boost/version.hpp>
00083 #if BOOST_VERSION >= 104600
00084 #include <boost/serialization/item_version_type.hpp>
00085 #endif
00086 
00087 namespace RTT
00088 {
00089     namespace mqueue
00090     {
00091 
00098         class binary_data_iarchive
00099         {
00100             std::streambuf& m_sb;
00101             int data_read;
00102         public:
00103             typedef char Elem;
00104             typedef binary_data_iarchive Archive;
00105 
00109             typedef boost::mpl::bool_<true> is_loading;
00113             typedef boost::mpl::bool_<false> is_saving;
00114 
00119             binary_data_iarchive(std::streambuf& bsb) :
00120                 m_sb(bsb), data_read(0)
00121             {
00122             }
00123 
00128             binary_data_iarchive(std::istream& is) :
00129                 m_sb(*is.rdbuf()), data_read(0)
00130             {
00131             }
00132 
00137             unsigned int get_library_version() { return 0; }
00138 
00144             void reset_object_address(const void * new_address, const void * old_address) {}
00145 
00149             void delete_created_pointers() {}
00150 
00156             template<class T>
00157             const boost::archive::detail::basic_pointer_iserializer *
00158             register_type(T * = NULL) {return 0;}
00159 
00166             void load_object(
00167                 void *t,
00168                 const /* BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) */ boost::archive::detail::basic_iserializer & bis
00169             ) {
00170                 assert(false);
00171             }
00172 
00177             template<class T>
00178             void load_override(T & t, BOOST_PFTO int){
00179                 load_a_type(t, boost::mpl::bool_<boost::serialization::implementation_level<T>::value == boost::serialization::primitive_type>() );
00180                 //archive::load(* this->This(), t);
00181             }
00182 
00188 #if 0
00189             void load_override(const boost::serialization::nvp<boost::serialization::collection_size_type> & t, int){
00190                  size_t x=0;
00191                  * this >> x;
00192                  t.value() = boost::serialization::collection_size_type(x);
00193              }
00194 #endif
00195             template<class T>
00196             void load_override(const boost::serialization::nvp<T> & t, int){
00197                 T& x(t.value());
00198                  * this >> x;
00199              }
00200 
00206             template<class T>
00207             void load_override(const boost::serialization::array<T> &t, int)
00208             {
00209                 boost::serialization::array<T> tmp(t.address(), t.count());
00210                 *this >> tmp;
00211             }
00212 
00218             template<class T>
00219             binary_data_iarchive &operator>>(T &t){
00220                 this->load_override(t, 0);
00221                 return * this;
00222             }
00223 
00229             template<class T>
00230             binary_data_iarchive &operator&(T &t){
00231                 return this->operator>>(t);
00232             }
00233 
00239             void load_binary(void *address, std::size_t count)
00240             {
00241                 // note: an optimizer should eliminate the following for char files
00242                 std::streamsize s = count / sizeof(Elem);
00243                 std::streamsize scount = m_sb.sgetn(
00244                         static_cast<Elem *> (address), s);
00245                 if (scount != static_cast<std::streamsize> (s))
00246 #if BOOST_VERSION >= 104400
00247                     boost::serialization::throw_exception(
00248                             boost::archive::archive_exception(
00249                                     boost::archive::archive_exception::input_stream_error));
00250 #else
00251                     boost::serialization::throw_exception(
00252                             boost::archive::archive_exception(
00253                                     boost::archive::archive_exception::stream_error));
00254 #endif
00255                 // note: an optimizer should eliminate the following for char files
00256                 s = count % sizeof(Elem);
00257                 if (0 < s)
00258                 {
00259                     //        if(is.fail())
00260                     //            boost::serialization::throw_exception(
00261                     //                archive_exception(archive_exception::stream_error)
00262                     //        );
00263                     Elem t;
00264                     scount = m_sb.sgetn(&t, 1);
00265                     if (scount != 1)
00266 #if BOOST_VERSION >= 104400
00267                         boost::serialization::throw_exception(
00268                                 boost::archive::archive_exception(
00269                                        boost::archive::archive_exception::input_stream_error));
00270 #else
00271                         boost::serialization::throw_exception(
00272                                 boost::archive::archive_exception(
00273                                         boost::archive::archive_exception::stream_error));
00274 #endif
00275                     std::memcpy(static_cast<char*> (address) + (count - s), &t,
00276                             s);
00277                 }
00278                 data_read += count;
00279             }
00280 
00286             template<class T>
00287             binary_data_iarchive &load_a_type(T &t,boost::mpl::true_){
00288                   load_binary(&t, sizeof(T));
00289                   return *this;
00290             }
00291 
00297             template<class T>
00298             binary_data_iarchive &load_a_type(T &t,boost::mpl::false_){
00299 #if BOOST_VERSION >= 104100
00300                 boost::archive::detail::load_non_pointer_type<binary_data_iarchive>::load_only::invoke(*this,t);
00301 #else
00302                 boost::archive::detail::load_non_pointer_type<binary_data_iarchive,T>::load_only::invoke(*this,t);
00303 #endif
00304                 return *this;
00305             }
00306 
00311             struct use_array_optimization {
00312                 template <class T>
00313                 #if defined(BOOST_NO_DEPENDENT_NESTED_DERIVATIONS)
00314                     struct apply {
00315                         typedef BOOST_DEDUCED_TYPENAME boost::serialization::is_bitwise_serializable<T>::type type;
00316                     };
00317                 #else
00318                     struct apply : public boost::serialization::is_bitwise_serializable<T> {};
00319                 #endif
00320             };
00321 
00325             template<class ValueType>
00326             void load_array(boost::serialization::array<ValueType>& a,
00327                             unsigned int)
00328             {
00329                 load_binary(a.address(), a.count()
00330                         * sizeof(ValueType));
00331             }
00332 
00336             int getArchiveSize() { return data_read; }
00337         };
00338 
00344         class binary_data_oarchive
00345         {
00346             std::streambuf & m_sb;
00347             int data_written;
00348             bool mdo_save;
00349         public:
00350             typedef char Elem;
00354             typedef boost::mpl::bool_<false> is_loading;
00358             typedef boost::mpl::bool_<true> is_saving;
00359 
00368             binary_data_oarchive(std::ostream& os,bool do_save = true) :
00369                 m_sb(*os.rdbuf()), data_written(0), mdo_save(do_save)
00370             {
00371             }
00372 
00381             binary_data_oarchive(std::streambuf& sb,bool do_save = true) :
00382                 m_sb(sb), data_written(0), mdo_save(do_save)
00383             {
00384             }
00385 
00390             unsigned int get_library_version() { return 0; }
00391 
00397             template<class T>
00398             const boost::archive::detail::basic_pointer_iserializer *
00399             register_type(T * = NULL) {return 0;}
00400 
00406             void save_object(
00407                 const void *x,
00408                 const boost::archive::detail::basic_oserializer & bos
00409             ) {
00410                 assert(false);
00411                 //(bos.save_object_data)(*this, x);
00412             }
00413 
00419             template<class T>
00420             binary_data_oarchive &operator<<(T const &t){
00421                     return save_a_type(t,boost::mpl::bool_< boost::serialization::implementation_level<T>::value == boost::serialization::primitive_type>() );
00422             }
00423 
00429             template<class T>
00430             binary_data_oarchive &operator&(T const &t){
00431                     return this->operator<<(t);
00432             }
00433 
00439             inline void save_binary(const void *address, std::size_t count)
00440             {
00441                 // figure number of elements to output - round up
00442                 count = (count + sizeof(Elem) - 1) / sizeof(Elem);
00443                 if (mdo_save) {
00444                     std::streamsize scount = m_sb.sputn(
00445                             static_cast<const Elem *> (address), count);
00446                     if (count != static_cast<std::size_t> (scount))
00447 #if BOOST_VERSION >= 104400
00448                         boost::serialization::throw_exception(
00449                                 boost::archive::archive_exception(
00450                                         boost::archive::archive_exception::output_stream_error));
00451 #else
00452                         boost::serialization::throw_exception(
00453                                 boost::archive::archive_exception(
00454                                         boost::archive::archive_exception::stream_error));
00455 #endif
00456                 }
00457                 data_written += count;
00458             }
00459 
00465             template<class T>
00466             binary_data_oarchive &save_a_type(T const &t,boost::mpl::true_){
00467                   save_binary(&t, sizeof(T));
00468                   return *this;
00469             }
00470 
00471 #if BOOST_VERSION >= 104600
00472             binary_data_oarchive &save_a_type(const boost::serialization::version_type & t,boost::mpl::true_){
00473                 // ignored, the load function is never called, so we don't store it.
00474                 return *this;
00475             }
00476             binary_data_oarchive &save_a_type(const boost::serialization::item_version_type & t,boost::mpl::true_){
00477                 // ignored, the load function is never called, so we don't store it.
00478                 return *this;
00479             }
00480 #endif
00481 
00487             template<class T>
00488             binary_data_oarchive &save_a_type(T const &t,boost::mpl::false_){
00489 #if BOOST_VERSION >= 104100
00490                   boost::archive::detail::save_non_pointer_type<binary_data_oarchive>::save_only::invoke(*this,t);
00491 #else
00492                   boost::archive::detail::save_non_pointer_type<binary_data_oarchive,T>::save_only::invoke(*this,t);
00493 #endif
00494                   return *this;
00495             }
00496 
00501             struct use_array_optimization {
00502                 template <class T>
00503                 #if defined(BOOST_NO_DEPENDENT_NESTED_DERIVATIONS)
00504                     struct apply {
00505                         typedef BOOST_DEDUCED_TYPENAME boost::serialization::is_bitwise_serializable<T>::type type;
00506                     };
00507                 #else
00508                     struct apply : public boost::serialization::is_bitwise_serializable<T> {};
00509                 #endif
00510             };
00511 
00515             template<class ValueType>
00516             void save_array(boost::serialization::array<ValueType> const& a,
00517                             unsigned int)
00518             {
00519                 save_binary(a.address(), a.count()
00520                         * sizeof(ValueType));
00521             }
00522 
00526             int getArchiveSize() { return data_written; }
00527         };
00528     }
00529 }
00530 
00531 BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(RTT::mqueue::binary_data_oarchive)
00532 BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(RTT::mqueue::binary_data_iarchive)
00533 
00534 #endif /* BINARY_DATA_ARCHIVE_HPP_ */