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