Line data Source code
1 :
2 : /* Copyright (c) 2012, Daniel Nachbaur <danielnachbaur@googlemail.com>
3 : *
4 : * This library is free software; you can redistribute it and/or modify it under
5 : * the terms of the GNU Lesser General Public License version 2.1 as published
6 : * by the Free Software Foundation.
7 : *
8 : * This library is distributed in the hope that it will be useful, but WITHOUT
9 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11 : * details.
12 : *
13 : * You should have received a copy of the GNU Lesser General Public License
14 : * along with this library; if not, write to the Free Software Foundation, Inc.,
15 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 : */
17 :
18 :
19 : template< typename T >
20 1 : void DataOStreamArchive::save_array( const boost::serialization::array< T >& a,
21 : unsigned int )
22 : {
23 1 : _stream << Array< const T >( a.address(), a.count( ));
24 1 : }
25 :
26 : template< class C, class T, class A >
27 1 : void DataOStreamArchive::save( const std::basic_string< C, T, A >& s )
28 : {
29 : // implementation only valid for narrow string
30 : BOOST_STATIC_ASSERT( sizeof(C) == sizeof(char));
31 1 : _stream << s;
32 1 : }
33 :
34 : template< typename T >
35 : typename boost::enable_if< boost::is_integral<T> >::type
36 12 : DataOStreamArchive::save( const T& t )
37 : {
38 : #if BOOST_VERSION < 104800
39 : namespace bs = boost::detail;
40 : #else
41 : namespace bs = boost::spirit::detail;
42 : #endif
43 :
44 12 : if( T temp = t )
45 : {
46 : // examine the number of bytes
47 : // needed to represent the number
48 11 : signed char size = 0;
49 5 : do
50 : {
51 : #pragma clang diagnostic push
52 : #pragma clang diagnostic ignored "-Wshift-count-overflow"
53 16 : temp >>= CHAR_BIT;
54 : #pragma clang diagnostic pop
55 16 : ++size;
56 : }
57 16 : while( temp != 0 && temp != (T) -1 );
58 :
59 : // encode the sign bit into the size
60 11 : _saveSignedChar( t > 0 ? size : -size );
61 10 : BOOST_ASSERT( t > 0 || boost::is_signed<T>::value) ;
62 :
63 : // we choose to use little endian because this way we just
64 : // save the first size bytes to the stream and skip the rest
65 11 : bs::store_little_endian<T, sizeof(T)>( &temp, t );
66 11 : save_binary( &temp, size );
67 : }
68 : else
69 : // zero optimization
70 1 : _saveSignedChar (0 );
71 12 : }
72 :
73 : template< typename T >
74 : typename boost::enable_if< boost::is_floating_point<T> >::type
75 1 : DataOStreamArchive::save( const T& t )
76 : {
77 : namespace fp = boost::spirit::math;
78 :
79 : typedef typename fp::detail::fp_traits<T>::type traits;
80 :
81 : // if the no_infnan flag is set we must throw here
82 1 : if( get_flags() & serialization::no_infnan && !fp::isfinite( t ))
83 0 : throw DataStreamArchiveException( t );
84 :
85 : // if you end here there are three possibilities:
86 : // 1. you're serializing a long double which is not portable
87 : // 2. you're serializing a double but have no 64 bit integer
88 : // 3. your machine is using an unknown floating point format
89 : // after reading the note above you still might decide to
90 : // deactivate this static assert and try if it works out.
91 : typename traits::bits bits;
92 : BOOST_STATIC_ASSERT( sizeof(bits) == sizeof(T));
93 : BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_iec559 );
94 :
95 : // examine value closely
96 1 : switch( fp::fpclassify( t ))
97 : {
98 : case FP_ZERO:
99 0 : bits = 0;
100 0 : break;
101 : case FP_NAN:
102 0 : bits = traits::exponent | traits::mantissa;
103 0 : break;
104 : case FP_INFINITE:
105 0 : bits = traits::exponent | (t<0) * traits::sign;
106 0 : break;
107 : case FP_SUBNORMAL:
108 : assert( std::numeric_limits<T>::has_denorm );
109 : case FP_NORMAL:
110 1 : traits::get_bits(t, bits);
111 1 : break;
112 : default:
113 0 : throw DataStreamArchiveException( t );
114 : }
115 :
116 1 : save( bits );
117 1 : }
|