| QxOrm 1.2.5 C++ Object Relational Mapping library

- Main Page
- Modules
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

portable_oarchive.hpp
Go to the documentation of this file.

    00001 /*****************************************************************************/
    00060 /*****************************************************************************/
    00061
    00062 #if _QX_SERIALIZE_PORTABLE_BINARY
    00063 #ifndef _QX_PORTABLE_BINARY_OARCHIVE_H_
    00064 #define _QX_PORTABLE_BINARY_OARCHIVE_H_
    00065
    00066 #ifdef _MSC_VER
    00067 #pragma once
    00068 #endif // _MSC_VER
    00069
    00070 #ifdef _MSC_VER
    00071 #pragma warning(push)
    00072 #pragma warning(disable:4996)
    00073 #pragma warning(disable:4661)
    00074 #endif // _MSC_VER
    00075
    00076 #include <ostream>
    00077
    00078 // basic headers
    00079 #include <boost/version.hpp>
    00080 #include <boost/utility/enable_if.hpp>
    00081 #include <boost/archive/binary_oarchive.hpp>
    00082
    00083 // endian and fpclassify
    00084 #if BOOST_VERSION < 103600
    00085 #include <boost/integer/endian.hpp>
    00086 #include <boost/math/fpclassify.hpp>
    00087 #else
    00088 #include <boost/spirit/home/support/detail/integer/endian.hpp>
    00089 #include <boost/spirit/home/support/detail/math/fpclassify.hpp>
    00090 #endif
    00091
    00092 // namespace alias
    00093 #if BOOST_VERSION < 103800
    00094 namespace fp = boost::math;
    00095 #else
    00096 namespace fp = boost::spirit::math;
    00097 #endif
    00098
    00099 // generic type traits for numeric types
    00100 #include <boost/type_traits/is_integral.hpp>
    00101 #include <boost/type_traits/is_signed.hpp>
    00102 #include <boost/type_traits/is_arithmetic.hpp>
    00103 #include <boost/type_traits/is_floating_point.hpp>
    00104
    00105 #include "portable_archive_exception.hpp"
    00106
    00107 // hint from Johan Rade: on VMS there is still support for
    00108 // the VAX floating point format and this macro detects it
    00109 #if defined(__vms) && defined(__DECCXX) && !__IEEE_FLOAT
    00110 #error "VAX floating point format is not supported!"
    00111 #endif
    00112
    00113 namespace eos {
    00114
    00115    // forward declaration
    00116    class portable_oarchive;
    00117
    00118    // convenience archive base class typedef
    00119    typedef boost::archive::binary_oarchive_impl<
    00120       portable_oarchive
    00121       #if BOOST_VERSION >= 103400
    00122          , std::ostream::char_type
    00123          , std::ostream::traits_type
    00124       #endif
    00125    > portable_oarchive_base;
    00126
    00142    class portable_oarchive : public portable_oarchive_base
    00143       #if BOOST_VERSION >= 103500
    00144          // mix-in helper class for serializing shared_ptr
    00145          , public boost::archive::detail::shared_ptr_helper
    00146       #endif
    00147    {
    00148       // workaround for gcc: use a dummy struct
    00149       // as additional argument type for overloading
    00150       template<int> struct dummy { dummy(int) {}};
    00151
    00152       // stores a signed char directly to stream
    00153       void save_signed_char(const signed char& c)
    00154       {
    00155          portable_oarchive_base::save(c);
    00156       }
    00157
    00158    public:
    00159
    00161       template<class T>
    00162       typename boost::disable_if<boost::is_arithmetic<T> >::type
    00163       save(const T & t, dummy<1> = 0)
    00164       {
    00165          portable_oarchive_base::save(t);
    00166       }
    00167
    00169       void save(const bool& b)
    00170       {
    00171          save_signed_char(b);
    00172          if (b) save_signed_char('T');
    00173       }
    00174
    00182       template <typename T>
    00183       typename boost::enable_if<boost::is_integral<T> >::type
    00184       save(const T & t, dummy<2> = 0)
    00185       {
    00186          if (T temp = t)
    00187          {
    00188             // examine the number of bytes
    00189             // needed to represent the number
    00190             signed char size = 0;
    00191             do { temp >>= CHAR_BIT; ++size; }
    00192             while (temp != 0 && temp != (T) -1);
    00193
    00194             // encode the sign bit into the size
    00195             save_signed_char(t > 0 ? size : -size);
    00196             BOOST_ASSERT(t > 0 || boost::is_signed<T>::value);
    00197
    00198             // we choose to use little endian because this way we just
    00199             // save the first size bytes to the stream and skip the rest
    00200             boost::detail::store_little_endian<T, sizeof(T)>(&temp, t);
    00201             save_binary(&temp, size);
    00202          }
    00203          // zero optimization
    00204          else save_signed_char(0);
    00205       }
    00206
    00234       template <typename T>
    00235       typename boost::enable_if<boost::is_floating_point<T> >::type
    00236       save(const T & t, dummy<3> = 0)
    00237       {
    00238          typedef typename fp::detail::fp_traits<T>::type traits;
    00239
    00240          // it is not supported to serialize infinity or not-a-number
    00241          if (!fp::isfinite(t)) throw portable_archive_exception(t);
    00242
    00243          // if you end here there are three possibilities:
    00244          // 1. you're serializing a long double which is not portable
    00245          // 2. you're serializing a double but have no 64 bit integer
    00246          // 3. your machine is using an unknown floating point format
    00247          // after reading the note above you still might decide to
    00248          // deactivate this static assert and try if it works out.
    00249          typename traits::bits bits;
    00250          BOOST_STATIC_ASSERT(sizeof(bits) == sizeof(T));
    00251          BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_iec559);
    00252
    00253          traits::get_bits(t, bits);
    00254          save(bits);
    00255       }
    00256
    00258       portable_oarchive(std::ostream& os, unsigned flags = 0)
    00259          // the base class constructor calls basic_binary_oarchive::init
    00260          // but also basic_binary_oprimitive::init which stores type sizes
    00261          // for comparison when loading them on a different platform
    00262          : portable_oarchive_base(os, flags | boost::archive::no_header)
    00263       {
    00264          // it is vital to have version information if the archive is
    00265          // to be parsed with a newer version of boost::serialization
    00266          // therefor we create a header, no header means boost 1.33
    00267          if (flags & boost::archive::no_header)
    00268             BOOST_ASSERT(archive_version == 3);
    00269          else
    00270          {
    00271             // write our minimalistic header (magic byte plus version)
    00272             // the boost archives write a string instead - by calling
    00273             // boost::archive::basic_binary_oarchive<derived_t>::init()
    00274             save_signed_char(magic_byte);
    00275
    00276             // write current version
    00277             operator<<(archive_version);
    00278          }
    00279       }
    00280    };
    00281
    00282 } // namespace eos
    00283
    00284 // required by export
    00285 #if BOOST_VERSION < 103500
    00286 #define BOOST_ARCHIVE_CUSTOM_OARCHIVE_TYPES eos::portable_oarchive
    00287 #else
    00288 BOOST_SERIALIZATION_REGISTER_ARCHIVE(eos::portable_oarchive)
    00289 #endif
    00290
    00291 namespace boost { namespace archive {
    00292
    00293    // explicitly instantiate for this type of binary stream
    00294    template class basic_binary_oarchive<eos::portable_oarchive>;
    00295
    00296    template class basic_binary_oprimitive<
    00297       eos::portable_oarchive
    00298       #if BOOST_VERSION < 103400
    00299          , std::ostream
    00300       #else
    00301          , std::ostream::char_type
    00302          , std::ostream::traits_type
    00303       #endif
    00304    >;
    00305
    00306    template class binary_oarchive_impl<
    00307       eos::portable_oarchive
    00308       #if BOOST_VERSION >= 103400
    00309          , std::ostream::char_type
    00310          , std::ostream::traits_type
    00311       #endif
    00312    >;
    00313
    00314 #if (! _QX_USE_EXPORT_DLL_BOOST_SERIALIZATION_SINGLETON)
    00315 #if (BOOST_VERSION > 103800)
    00316    template class detail::archive_serializer_map<eos::portable_oarchive>;
    00317 #else
    00318    template class detail::archive_pointer_oserializer<eos::portable_oarchive>;
    00319 #endif // (BOOST_VERSION > 103800)
    00320 #endif // (! _QX_USE_EXPORT_DLL_BOOST_SERIALIZATION_SINGLETON)
    00321
    00322 } } // namespace boost::archive
    00323
    00324 #ifdef _MSC_VER
    00325 #pragma warning(pop)
    00326 #endif // _MSC_VER
    00327
    00328 #endif // _QX_PORTABLE_BINARY_OARCHIVE_H_
    00329 #endif //_QX_SERIALIZE_PORTABLE_BINARY