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 : #include "dataIStream.h"
19 : #include "dataStreamArchiveException.h"
20 :
21 : namespace co
22 : {
23 :
24 : template< typename T >
25 1 : void DataIStreamArchive::load_array( boost::serialization::array< T >& a,
26 : unsigned int )
27 : {
28 1 : _stream >> Array< T >( a.address(), a.count( ));
29 1 : }
30 :
31 : template< class C, class T, class A >
32 1 : void DataIStreamArchive::load( std::basic_string< C, T, A >& s )
33 : {
34 : // implementation only valid for narrow string
35 : BOOST_STATIC_ASSERT( sizeof(C) == sizeof(char));
36 1 : _stream >> s;
37 1 : }
38 :
39 : template< typename T >
40 : typename boost::enable_if< boost::is_integral<T> >::type
41 13 : DataIStreamArchive::load( T& t )
42 : {
43 : #if BOOST_VERSION < 104800
44 : namespace bs = boost::detail;
45 : #else
46 : namespace bs = boost::spirit::detail;
47 : #endif
48 :
49 : // get the number of bytes in the stream
50 13 : if( signed char size = _loadSignedChar( ))
51 : {
52 : // check for negative value in unsigned type
53 10 : if( size < 0 && boost::is_unsigned<T>::value )
54 0 : throw DataStreamArchiveException();
55 :
56 : // check that our type T is large enough
57 11 : else if( (unsigned)abs(size) > sizeof(T))
58 0 : throw DataStreamArchiveException( size );
59 :
60 : // reconstruct the value
61 11 : T temp = size < 0 ? -1 : 0;
62 11 : load_binary( &temp, abs(size));
63 :
64 : // load the value from little endian - is is then converted
65 : // to the target type T and fits it because size <= sizeof(T)
66 11 : t = bs::load_little_endian<T, sizeof(T)>( &temp );
67 : }
68 : else
69 : // zero optimization
70 2 : t = 0;
71 13 : }
72 :
73 : template< typename T >
74 : typename boost::enable_if<boost::is_floating_point<T> >::type
75 1 : DataIStreamArchive::load( T& t )
76 : {
77 : namespace fp = boost::spirit::math;
78 : typedef typename fp::detail::fp_traits<T>::type traits;
79 :
80 : // if you end here there are three possibilities:
81 : // 1. you're serializing a long double which is not portable
82 : // 2. you're serializing a double but have no 64 bit integer
83 : // 3. your machine is using an unknown floating point format
84 : // after reading the note above you still might decide to
85 : // deactivate this static assert and try if it works out.
86 : typename traits::bits bits;
87 : BOOST_STATIC_ASSERT( sizeof(bits) == sizeof(T));
88 : BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_iec559 );
89 :
90 1 : load( bits );
91 1 : traits::set_bits( t, bits );
92 :
93 : // if the no_infnan flag is set we must throw here
94 1 : if( get_flags() & serialization::no_infnan && !fp::isfinite( t ))
95 0 : throw DataStreamArchiveException( t );
96 :
97 : // if you end here your floating point type does not support
98 : // denormalized numbers. this might be the case even though
99 : // your type conforms to IEC 559 (and thus to IEEE 754)
100 : if( std::numeric_limits<T>::has_denorm == std::denorm_absent &&
101 : fp::fpclassify(t) == (int)FP_SUBNORMAL ) // GCC4
102 : {
103 : throw DataStreamArchiveException( t );
104 : }
105 1 : }
106 :
107 : }
|