ISIS Core Library 0.7.2 (api 3.0.0)

/scr/tee1/isis/lib/Core/DataStorage/endianess.hpp

Go to the documentation of this file.
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