Collage
0.6.1
|
00001 00002 /* Copyright (c) 2012, Daniel Nachbaur <danielnachbaur@googlemail.com> 00003 * This library is free software; you can redistribute it and/or modify it under 00004 * the terms of the GNU Lesser General Public License version 2.1 as published 00005 * by the Free Software Foundation. 00006 * 00007 * This library is distributed in the hope that it will be useful, but WITHOUT 00008 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00009 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 00010 * details. 00011 * 00012 * You should have received a copy of the GNU Lesser General Public License 00013 * along with this library; if not, write to the Free Software Foundation, Inc., 00014 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00015 */ 00016 00017 00018 template< typename T > 00019 void DataOStreamArchive::save_array( const boost::serialization::array< T >& a, 00020 unsigned int ) 00021 { 00022 save_binary( a.address(), a.count() * sizeof( T )); 00023 } 00024 00025 template< class C, class T, class A > 00026 void DataOStreamArchive::save( const std::basic_string< C, T, A >& s ) 00027 { 00028 // implementation only valid for narrow string 00029 BOOST_STATIC_ASSERT( sizeof(C) == sizeof(char)); 00030 _stream << s; 00031 } 00032 00033 template< typename T > 00034 typename boost::enable_if< boost::is_integral<T> >::type 00035 DataOStreamArchive::save( const T& t ) 00036 { 00037 #if BOOST_VERSION < 104800 00038 namespace bs = boost::detail; 00039 #else 00040 namespace bs = boost::spirit::detail; 00041 #endif 00042 00043 if( T temp = t ) 00044 { 00045 // examine the number of bytes 00046 // needed to represent the number 00047 signed char size = 0; 00048 do 00049 { 00050 temp >>= CHAR_BIT; 00051 ++size; 00052 } 00053 while( temp != 0 && temp != (T) -1 ); 00054 00055 // encode the sign bit into the size 00056 _saveSignedChar( t > 0 ? size : -size ); 00057 BOOST_ASSERT( t > 0 || boost::is_signed<T>::value) ; 00058 00059 // we choose to use little endian because this way we just 00060 // save the first size bytes to the stream and skip the rest 00061 bs::store_little_endian<T, sizeof(T)>( &temp, t ); 00062 save_binary( &temp, size ); 00063 } 00064 else 00065 // zero optimization 00066 _saveSignedChar (0 ); 00067 } 00068 00069 template< typename T > 00070 typename boost::enable_if< boost::is_floating_point<T> >::type 00071 DataOStreamArchive::save( const T& t ) 00072 { 00073 namespace fp = boost::spirit::math; 00074 00075 typedef typename fp::detail::fp_traits<T>::type traits; 00076 00077 // if the no_infnan flag is set we must throw here 00078 if( get_flags() & no_infnan && !fp::isfinite( t )) 00079 throw DataStreamArchiveException( t ); 00080 00081 // if you end here there are three possibilities: 00082 // 1. you're serializing a long double which is not portable 00083 // 2. you're serializing a double but have no 64 bit integer 00084 // 3. your machine is using an unknown floating point format 00085 // after reading the note above you still might decide to 00086 // deactivate this static assert and try if it works out. 00087 typename traits::bits bits; 00088 BOOST_STATIC_ASSERT( sizeof(bits) == sizeof(T)); 00089 BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_iec559 ); 00090 00091 // examine value closely 00092 switch( fp::fpclassify( t )) 00093 { 00094 case FP_ZERO: 00095 bits = 0; 00096 break; 00097 case FP_NAN: 00098 bits = traits::exponent | traits::mantissa; 00099 break; 00100 case FP_INFINITE: 00101 bits = traits::exponent | (t<0) * traits::sign; 00102 break; 00103 case FP_SUBNORMAL: 00104 assert( std::numeric_limits<T>::has_denorm ); 00105 case FP_NORMAL: 00106 traits::get_bits(t, bits); 00107 break; 00108 default: 00109 throw DataStreamArchiveException( t ); 00110 } 00111 00112 save( bits ); 00113 }