#ifndef BINARY_OBJECT_ARCHIVE_HPP_ #define BINARY_OBJECT_ARCHIVE_HPP_ // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . // (C) Copyright 2009 Peter Soetens - http://www.thesourceworks.com . // Use, modification and distribution is subject to the Boost Software // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // See http://www.boost.org for updates, documentation, and revision history. /** * @file binary_object_archive.hpp * * This file implements a 'level 2' binary archiver of serializable objects. * * It can be used if only 'Plain Old Data' must be stored and has the advantage * that it doesn't allocate memory, nor during construction of the archive, nor * during serializing/deserializing. * * No class information or cross-references are stored. * * This archive is header-only and does not depend on the serialization DLL. * */ #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace archive { /** * This archive is capable of loading objects of * serialization level 1 and 2 from a binary, non-portable format. * @see binary_object_oarchive * @see */ class binary_object_iarchive { std::streambuf& m_sb; public: typedef char Elem; /** * Loading Archive Concept::is_loading */ typedef mpl::bool_ is_loading; /** * Loading Archive Concept::is_saving */ typedef mpl::bool_ is_saving; /** * Constructor from a standard output stream. * @param os The stream to serialize from. */ binary_object_iarchive(std::streambuf& bsb) : m_sb(bsb) { } /** * Constructor from a standard stream buffer. * @param os The buffer to serialize from. */ binary_object_iarchive(std::istream& is) : m_sb(*is.rdbuf()) { } /** * Loading Archive Concept::get_library_version() * @return This library's version. */ unsigned int get_library_version() { return 0; } /** * Loading Archive Concept::reset_object_address(v,u) * @param new_address * @param old_address */ void reset_object_address(const void * new_address, const void * old_address) {} /** * Loading Archive Concept::delete_created_pointers() */ void delete_created_pointers() {} /** * Loading Archive Concept::register_type() and ::register_type(u) * @param The data type to register in this archive. * @return */ template const detail::basic_pointer_iserializer * register_type(T * = NULL) {return 0;} /** * Note: not in LoadArchive concept but required when we use archive::load ! * @param x * @param bos */ void load_object( void *t, const /* BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) */ detail::basic_iserializer & bis ) {} /** * Loading Archive Concept::operator>> * @param t The type to load. * @return *this */ template binary_object_iarchive &operator>>(T &t){ return load_a_type(t, boost::mpl::bool_::value == serialization::primitive_type>() ); } /** * Loading Archive Concept::operator& * @param t The type to load. * @return *this */ template binary_object_iarchive &operator&(T &t){ return this->operator>>(t); } /** * Loading Archive Concept::load_binary(u, count) * @param address The place in memory where data must be written. * @param count The number of bytes to load. */ void load_binary(void *address, std::size_t count) { // note: an optimizer should eliminate the following for char files std::streamsize s = count / sizeof(Elem); std::streamsize scount = m_sb.sgetn( static_cast (address), s); if (scount != static_cast (s)) boost::serialization::throw_exception( boost::archive::archive_exception( boost::archive::archive_exception::stream_error)); // note: an optimizer should eliminate the following for char files s = count % sizeof(Elem); if (0 < s) { // if(is.fail()) // boost::serialization::throw_exception( // archive_exception(archive_exception::stream_error) // ); Elem t; scount = m_sb.sgetn(&t, 1); if (scount != 1) boost::serialization::throw_exception( boost::archive::archive_exception( boost::archive::archive_exception::stream_error)); std::memcpy(static_cast (address) + (count - s), &t, s); } } /** * Specialisation for writing out primitive types. * @param t primitive data (bool, int,...) * @return *this */ template binary_object_iarchive &load_a_type(T &t,boost::mpl::true_){ load_binary(&t, sizeof(T)); return *this; } /** * Specialisation for writing out composite types (objects). * @param t a serializable class or struct. * @return *this */ template binary_object_iarchive &load_a_type(T &t,boost::mpl::false_){ archive::load(*this, t); return *this; } /** * We provide an optimized load for all fundamental types * typedef serialization::is_bitwise_serializable use_array_optimization; */ struct use_array_optimization { template #if defined(BOOST_NO_DEPENDENT_NESTED_DERIVATIONS) struct apply { typedef BOOST_DEDUCED_TYPENAME boost::serialization::is_bitwise_serializable::type type; }; #else struct apply : public boost::serialization::is_bitwise_serializable {}; #endif }; /** * The optimized save_array dispatches to save_binary */ template void load_array(boost::serialization::array& a, unsigned int) { load_binary(a.address(), a.count() * sizeof(ValueType)); } }; /** * This archive is capable of saving objects of serialization level 1 and 2 * in a binary, non-portable format. * @see binary_object_iarchive */ class binary_object_oarchive { std::streambuf & m_sb; public: typedef char Elem; /** * Saving Archive Concept::is_loading */ typedef mpl::bool_ is_loading; /** * Saving Archive Concept::is_saving */ typedef mpl::bool_ is_saving; /** * Constructor from a standard output stream. * @param os The stream to serialize to */ binary_object_oarchive(std::ostream& os) : m_sb(*os.rdbuf()) { } /** * Constructor from a standard stream buffer. * @param os The buffer to serialize to. */ binary_object_oarchive(std::streambuf& sb) : m_sb(sb) { } /** * Saving Archive Concept::get_library_version() * @return This library's version. */ unsigned int get_library_version() { return 0; } /** * Saving Archive Concept::register_type() and ::register_type(u) * @param The data type to register in this archive. * @return */ template const detail::basic_pointer_iserializer * register_type(T * = NULL) {return 0;} /** * Note: not in LoadArchive concept but required when we use archive::save ! * @param x * @param bos */ void save_object( const void *x, const detail::basic_oserializer & bos ) {} /** * Saving Archive Concept::operator<< * @param t The type to save. * @return *this */ template binary_object_oarchive &operator<<(T const &t){ return save_a_type(t,boost::mpl::bool_< serialization::implementation_level::value == serialization::primitive_type>() ); } /** * Saving Archive Concept::operator& * @param t The type to save. * @return *this */ template binary_object_oarchive &operator&(T const &t){ return this->operator<<(t); } /** * Saving Archive Concept::save_binary(u, count) * @param address The place where data is located in memory. * @param count The number of bytes to save. */ inline void save_binary(const void *address, std::size_t count) { // figure number of elements to output - round up count = (count + sizeof(Elem) - 1) / sizeof(Elem); std::streamsize scount = m_sb.sputn( static_cast (address), count); if (count != static_cast (scount)) boost::serialization::throw_exception( boost::archive::archive_exception( boost::archive::archive_exception::stream_error)); } /** * Specialisation for writing out primitive types. * @param t primitive data (bool, int,...) * @return *this */ template binary_object_oarchive &save_a_type(T const &t,boost::mpl::true_){ save_binary(&t, sizeof(T)); return *this; } /** * Specialisation for writing out composite types (objects). * @param t a serializable class or struct. * @return *this */ template binary_object_oarchive &save_a_type(T const &t,boost::mpl::false_){ archive::save(*this, t); return *this; } /** * We provide an optimized load for all fundamental types * typedef serialization::is_bitwise_serializable use_array_optimization; */ struct use_array_optimization { template #if defined(BOOST_NO_DEPENDENT_NESTED_DERIVATIONS) struct apply { typedef BOOST_DEDUCED_TYPENAME boost::serialization::is_bitwise_serializable::type type; }; #else struct apply : public boost::serialization::is_bitwise_serializable {}; #endif }; /** * The optimized save_array dispatches to save_binary */ template void save_array(boost::serialization::array const& a, unsigned int) { save_binary(a.address(), a.count() * sizeof(ValueType)); } }; } } #endif /* BINARY_OBJECT_ARCHIVE_HPP_ */