ISIS Core Library 0.7.2 (api 3.0.0)
|
00001 #ifndef ENDIANESS_HPP 00002 #define ENDIANESS_HPP 00003 00004 #include <boost/type_traits/is_arithmetic.hpp> 00005 #include "../CoreUtils/types.hpp" 00006 #include "../CoreUtils/value.hpp" 00007 #include <bits/byteswap.h> 00008 00009 namespace isis 00010 { 00011 namespace data 00012 { 00014 namespace _internal 00015 { 00016 00017 // actual implementation of the scalar-byte-swap (generic version) 00018 template<uint_fast8_t SIZE> struct SwapImpl { 00019 template<typename TYPE> static TYPE doSwap( const TYPE &src ) { 00020 TYPE ret = 0; 00021 uint8_t *retPtr = reinterpret_cast<uint8_t *>( &ret ); 00022 const uint8_t *srcPtr = reinterpret_cast<const uint8_t *>( &src ); 00023 00024 for ( uint_fast8_t i = 0; i < SIZE; i++ ) 00025 retPtr[i] = srcPtr[SIZE - 1 - i]; 00026 00027 return ret; 00028 } 00029 }; 00030 00031 // specialisation (swapping 1 byte might be a bit useless) 00032 template<> struct SwapImpl<1> { 00033 template<typename TYPE> static TYPE doSwap( const TYPE &src ) {return src;} 00034 }; 00035 00036 //specializations for 16 32 and 64 bit 00037 template<> struct SwapImpl<2> { 00038 template<typename TYPE> static TYPE doSwap( const TYPE &src ) {return __bswap_16(src);} 00039 }; 00040 template<> struct SwapImpl<4> { 00041 template<typename TYPE> static TYPE doSwap( const TYPE &src ) {return __bswap_32(src);} 00042 }; 00043 template<> struct SwapImpl<8> { 00044 template<typename TYPE> static TYPE doSwap( const TYPE &src ) {return __bswap_64(src);} 00045 }; 00046 00047 00048 00049 // gatekeeper for SwapImpl (do not allow swapping of types we do not know about) 00050 template<typename TYPE, bool IS_NUM> struct EndianSwapper { 00051 static TYPE swap( const TYPE &src ) { 00052 LOG( Runtime, error ) << "Sorry, endianess swap for " << util::Value<TYPE>::staticName() << " is not supportet"; 00053 return src; 00054 } 00055 }; 00056 00057 // plain numeric scalar - directly use doSwap 00058 template<typename TYPE> struct EndianSwapper<TYPE, true> { 00059 static TYPE swap( const TYPE &src ) {return SwapImpl<sizeof( TYPE )>::doSwap( src );} 00060 }; 00061 00062 //color-struct - do swap for each color 00063 template<typename TYPE> struct EndianSwapper<util::color<TYPE>, false> { 00064 static util::color<TYPE> swap( const util::color<TYPE> &src ) { 00065 util::color<TYPE> ret; 00066 ret.r = EndianSwapper<TYPE, boost::is_arithmetic<TYPE>::value>::swap( src.r ); 00067 ret.g = EndianSwapper<TYPE, boost::is_arithmetic<TYPE>::value>::swap( src.g ); 00068 ret.b = EndianSwapper<TYPE, boost::is_arithmetic<TYPE>::value>::swap( src.b ); 00069 return ret; 00070 } 00071 }; 00072 00073 // lists - do swap for each entry 00074 template<typename TYPE> struct EndianSwapper<std::list<TYPE>, false> { 00075 static std::list<TYPE> swap( const std::list<TYPE> &src ) { 00076 std::list<TYPE> ret; 00077 std::transform( src.begin(), src.end(), ret.begin(), EndianSwapper<TYPE, boost::is_arithmetic<TYPE>::value>::swap ); 00078 return ret; 00079 } 00080 }; 00081 00082 // FixedVector - do swap for each entry 00083 template<typename TYPE, size_t SIZE> struct EndianSwapper<util::FixedVector<TYPE, SIZE>, false> { 00084 static util::FixedVector<TYPE, SIZE> swap( const util::FixedVector<TYPE, SIZE> &src ) { 00085 util::FixedVector<TYPE, SIZE> ret; 00086 std::transform( src.begin(), src.end(), ret.begin(), EndianSwapper<TYPE, boost::is_arithmetic<TYPE>::value>::swap ); 00087 return ret; 00088 } 00089 }; 00090 } //_internal 00092 00093 // public interface 00094 template<typename T> static T endianSwap( const T &var ) 00095 { 00096 return _internal::EndianSwapper<T, boost::is_arithmetic< T >::value >::swap( var ); 00097 } 00098 template<typename ITER, typename TITER> static void endianSwapArray( const ITER begin, const ITER end, TITER target ) 00099 { 00100 for( ITER i = begin; i != end; i++, target++ ) { 00101 *target = endianSwap( *i ); 00102 } 00103 } 00104 00105 } 00106 } 00107 #endif //ENDIANESS_HPP