Collage
0.6.1
|
00001 00002 /* Copyright (c) 2012, Daniel Nachbaur <danielnachbaur@googlemail.com> 00003 * 00004 * This library is free software; you can redistribute it and/or modify it under 00005 * the terms of the GNU Lesser General Public License version 2.1 as published 00006 * by the Free Software Foundation. 00007 * 00008 * This library is distributed in the hope that it will be useful, but WITHOUT 00009 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00010 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 00011 * details. 00012 * 00013 * You should have received a copy of the GNU Lesser General Public License 00014 * along with this library; if not, write to the Free Software Foundation, Inc., 00015 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00016 */ 00017 00018 00019 template< typename T > 00020 void DataIStreamArchive::load_array( boost::serialization::array< T >& a, 00021 unsigned int ) 00022 { 00023 load_binary( a.address(), a.count() * sizeof( T )); 00024 } 00025 00026 template< class C, class T, class A > 00027 void DataIStreamArchive::load( std::basic_string< C, T, A >& s ) 00028 { 00029 // implementation only valid for narrow string 00030 BOOST_STATIC_ASSERT( sizeof(C) == sizeof(char)); 00031 _stream >> s; 00032 } 00033 00034 template< typename T > 00035 typename boost::enable_if< boost::is_integral<T> >::type 00036 DataIStreamArchive::load( T& t ) 00037 { 00038 #if BOOST_VERSION < 104800 00039 namespace bs = boost::detail; 00040 #else 00041 namespace bs = boost::spirit::detail; 00042 #endif 00043 00044 // get the number of bytes in the stream 00045 if( signed char size = _loadSignedChar( )) 00046 { 00047 // check for negative value in unsigned type 00048 if( size < 0 && boost::is_unsigned<T>::value ) 00049 throw DataStreamArchiveException(); 00050 00051 // check that our type T is large enough 00052 else if( (unsigned)abs(size) > sizeof(T)) 00053 throw DataStreamArchiveException( size ); 00054 00055 // reconstruct the value 00056 T temp = size < 0 ? -1 : 0; 00057 load_binary( &temp, abs(size)); 00058 00059 // load the value from little endian - is is then converted 00060 // to the target type T and fits it because size <= sizeof(T) 00061 t = bs::load_little_endian<T, sizeof(T)>( &temp ); 00062 } 00063 else 00064 // zero optimization 00065 t = 0; 00066 } 00067 00068 template< typename T > 00069 typename boost::enable_if<boost::is_floating_point<T> >::type 00070 DataIStreamArchive::load( T& t ) 00071 { 00072 namespace fp = boost::spirit::math; 00073 00074 typedef typename fp::detail::fp_traits<T>::type traits; 00075 00076 // if you end here there are three possibilities: 00077 // 1. you're serializing a long double which is not portable 00078 // 2. you're serializing a double but have no 64 bit integer 00079 // 3. your machine is using an unknown floating point format 00080 // after reading the note above you still might decide to 00081 // deactivate this static assert and try if it works out. 00082 typename traits::bits bits; 00083 BOOST_STATIC_ASSERT( sizeof(bits) == sizeof(T)); 00084 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_iec559 ); 00085 00086 load( bits ); 00087 traits::set_bits( t, bits ); 00088 00089 // if the no_infnan flag is set we must throw here 00090 if( get_flags() & no_infnan && !fp::isfinite( t )) 00091 throw DataStreamArchiveException( t ); 00092 00093 // if you end here your floating point type does not support 00094 // denormalized numbers. this might be the case even though 00095 // your type conforms to IEC 559 (and thus to IEEE 754) 00096 if( std::numeric_limits<T>::has_denorm == std::denorm_absent && 00097 fp::fpclassify(t) == (int)FP_SUBNORMAL ) // GCC4 00098 { 00099 throw DataStreamArchiveException( t ); 00100 } 00101 }