Line data Source code
1 :
2 : /* Copyright (c) 2012, Daniel Nachbaur <danielnachbaur@googlemail.com>
3 : * 2012, Stefan Eilemann <eile@eyescale.ch>
4 : *
5 : * This file is part of Collage <https://github.com/Eyescale/Collage>
6 : *
7 : * This library is free software; you can redistribute it and/or modify it under
8 : * the terms of the GNU Lesser General Public License version 2.1 as published
9 : * by the Free Software Foundation.
10 : *
11 : * This library is distributed in the hope that it will be useful, but WITHOUT
12 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14 : * details.
15 : *
16 : * You should have received a copy of the GNU Lesser General Public License
17 : * along with this library; if not, write to the Free Software Foundation, Inc.,
18 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 : */
20 :
21 : // Based on portable_oarchive.hpp
22 : // https://github.com/boost-vault/serialization/eos_portable_archive.zip
23 : // Copyright Christian Pfligersdorffer, 2007. All rights reserved.
24 : //
25 : // Distributed under the Boost Software License, Version 1.0. (See
26 : // accompanying file LICENSE_1_0.txt or copy at
27 : // http://www.boost.org/LICENSE_1_0.txt)
28 :
29 : #ifndef CO_DATAOSTREAMARCHIVE_H
30 : #define CO_DATAOSTREAMARCHIVE_H
31 :
32 : #include <co/api.h>
33 : #include <co/dataOStream.h>
34 : #include <co/dataStreamArchiveException.h>
35 :
36 : #include <boost/version.hpp>
37 :
38 : #include <boost/archive/basic_binary_oarchive.hpp>
39 : #include <boost/archive/detail/register_archive.hpp>
40 : #include <boost/serialization/is_bitwise_serializable.hpp>
41 : #if BOOST_VERSION >= 104400
42 : # include <boost/serialization/item_version_type.hpp>
43 : #endif
44 :
45 : #include <boost/spirit/home/support/detail/endian.hpp>
46 : #include <boost/spirit/home/support/detail/math/fpclassify.hpp>
47 :
48 : #include <boost/type_traits/is_integral.hpp>
49 : #include <boost/type_traits/is_signed.hpp>
50 : #include <boost/type_traits/is_floating_point.hpp>
51 :
52 :
53 : namespace co
54 : {
55 :
56 : /** A boost.serialization output archive writing to a co::DataOStream. */
57 6 : class DataOStreamArchive
58 : : public boost::archive::basic_binary_oarchive< DataOStreamArchive >
59 : {
60 : typedef boost::archive::basic_binary_oarchive< DataOStreamArchive > Super;
61 :
62 : public:
63 : /** Construct a new serialization archive. @version 1.0 */
64 : CO_API explicit DataOStreamArchive( DataOStream& stream );
65 :
66 : /** @internal archives are expected to support this function. */
67 : CO_API void save_binary( const void* data, std::size_t size );
68 :
69 : /** @internal use optimized save for arrays. */
70 : template< typename T >
71 : void save_array( const boost::serialization::array< T >& a, unsigned int );
72 :
73 : /** @internal enable serialization optimization for arrays. */
74 : struct use_array_optimization
75 : {
76 : template< class T >
77 : struct apply
78 : : public boost::serialization::is_bitwise_serializable< T > {};
79 : };
80 :
81 : private:
82 : friend class boost::archive::save_access;
83 :
84 : /**
85 : * Save boolean.
86 : *
87 : * Saving bool directly, not by const reference because of tracking_type's
88 : * operator (bool).
89 : */
90 : CO_API void save( bool b );
91 :
92 : /** Save string types. */
93 : template< class C, class T, class A >
94 : void save( const std::basic_string< C, T, A >& s );
95 :
96 : /**
97 : * Save integer types.
98 : *
99 : * First we save the size information ie. the number of bytes that hold the
100 : * actual data. We subsequently transform the data using store_little_endian
101 : * and store non-zero bytes to the stream.
102 : */
103 : template< typename T >
104 : typename boost::enable_if< boost::is_integral<T> >::type save( const T& t );
105 :
106 : /**
107 : * Save floating point types.
108 : *
109 : * We simply rely on fp_traits to extract the bit pattern into an (unsigned)
110 : * integral type and store that into the stream. Francois Mauger provided
111 : * standardized behaviour for special values like inf and NaN, that need to
112 : * be serialized in his application.
113 : *
114 : * \note by Johan Rade (author of the floating point utilities library):
115 : * Be warned that the math::detail::fp_traits<T>::type::get_bits() function
116 : * is *not* guaranteed to give you all bits of the floating point number. It
117 : * will give you all bits if and only if there is an integer type that has
118 : * the same size as the floating point you are copying from. It will not
119 : * give you all bits for double if there is no uint64_t. It will not give
120 : * you all bits for long double if sizeof(long double) > 8 or there is no
121 : * uint64_t.
122 : *
123 : * The member fp_traits<T>::type::coverage will tell you whether all bits
124 : * are copied. This is a typedef for either math::detail::all_bits or
125 : * math::detail::not_all_bits.
126 : *
127 : * If the function does not copy all bits, then it will copy the most
128 : * significant bits. So if you serialize and deserialize the way you
129 : * describe, and fp_traits<T>::type::coverage is math::detail::not_all_bits,
130 : * then your floating point numbers will be truncated. This will introduce
131 : * small rounding off errors.
132 : */
133 : template< typename T >
134 : typename boost::enable_if< boost::is_floating_point<T> >::type
135 : save( const T& t );
136 :
137 : #if BOOST_VERSION >= 104400
138 : // in boost 1.44 version_type was splitted into library_version_type and
139 : // item_version_type, plus a whole bunch of additional strong typedefs
140 : CO_API void save( const boost::archive::library_version_type& version );
141 : CO_API void save( const boost::archive::class_id_type& class_id );
142 : CO_API void save( const boost::serialization::item_version_type& class_id );
143 : CO_API
144 : void save( const boost::serialization::collection_size_type& class_id );
145 : CO_API void save( const boost::archive::object_id_type& object_id );
146 : CO_API void save( const boost::archive::version_type& version );
147 : #endif
148 :
149 : CO_API void _saveSignedChar( const signed char& c );
150 :
151 : DataOStream& _stream;
152 : };
153 :
154 : #include "dataOStreamArchive.ipp" // template implementation
155 :
156 : }
157 :
158 : BOOST_SERIALIZATION_REGISTER_ARCHIVE(co::DataOStreamArchive)
159 : BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(co::DataOStreamArchive)
160 :
161 : #endif //CO_DATAOSTREAMARCHIVE_H
|