$search
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_ */