Collage  1.2.1
High-performance C++ library for developing object-oriented distributed applications.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 "dataIStream.h"
19 #include "dataStreamArchiveException.h"
20 
21 namespace co
22 {
23 
24 template< typename T >
25 void DataIStreamArchive::load_array( boost::serialization::array< T >& a,
26  unsigned int )
27 {
28  _stream >> Array< T >( a.address(), a.count( ));
29 }
30 
31 template< class C, class T, class A >
32 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  _stream >> s;
37 }
38 
39 template< typename T >
40 typename boost::enable_if< boost::is_integral<T> >::type
41 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  if( signed char size = _loadSignedChar( ))
51  {
52  // check for negative value in unsigned type
53  if( size < 0 && boost::is_unsigned<T>::value )
54  throw DataStreamArchiveException();
55 
56  // check that our type T is large enough
57  else if( (unsigned)abs(size) > sizeof(T))
58  throw DataStreamArchiveException( size );
59 
60  // reconstruct the value
61  T temp = size < 0 ? -1 : 0;
62  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  t = bs::load_little_endian<T, sizeof(T)>( &temp );
67  }
68  else
69  // zero optimization
70  t = 0;
71 }
72 
73 template< typename T >
74 typename boost::enable_if<boost::is_floating_point<T> >::type
75 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  load( bits );
91  traits::set_bits( t, bits );
92 
93  // if the no_infnan flag is set we must throw here
94  if( get_flags() & serialization::no_infnan && !fp::isfinite( t ))
95  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 }
106 
107 }