/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2011 Mathieu Malaterre All rights reserved. See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #ifndef GDCMBYTESWAP_TXX #define GDCMBYTESWAP_TXX #include "gdcmByteSwap.h" #include #include // abort namespace gdcm { /* template (class T) { void bswap(inout T i) { byte* p = cast(byte*)&i; for (int b = 0; b < T.size/2; ++b) instance swap(byte).swap(p[b], p[T.size-1-b]); } } */ // Machine definitions #ifdef GDCM_WORDS_BIGENDIAN template bool ByteSwap::SystemIsBigEndian() { return true; } template bool ByteSwap::SystemIsLittleEndian() { return false; } #else template bool ByteSwap::SystemIsBigEndian() { return false; } template bool ByteSwap::SystemIsLittleEndian() { return true; } #endif template void ByteSwap::Swap(T &p) { #ifdef GDCM_WORDS_BIGENDIAN ByteSwap::SwapFromSwapCodeIntoSystem(p, SwapCode::LittleEndian); #else ByteSwap::SwapFromSwapCodeIntoSystem(p, SwapCode::BigEndian); #endif } // Swaps the bytes so they agree with the processor order template void ByteSwap::SwapFromSwapCodeIntoSystem(T &a, SwapCode const &swapcode) { //std::cerr << "sizeof(T)= " << sizeof(T) << " " << (int)a << std::endl; switch(sizeof(T)) { case 1: break; case 2: Swap4(a, swapcode); break; case 4: Swap8(a, swapcode); break; default: std::cerr << "Impossible" << std::endl; abort(); } } template void ByteSwap::SwapRange(T *p, unsigned int num) { for(unsigned int i=0; i::Swap(p[i]); } } template void ByteSwap::SwapRangeFromSwapCodeIntoSystem(T *p, SwapCode const &sc, std::streamoff num) { for( std::streamoff i=0; i::SwapFromSwapCodeIntoSystem(p[i], sc); } } // Private: // template void Swap4(T &a, SwapCode const &swapcode) { #ifndef GDCM_WORDS_BIGENDIAN if ( swapcode == gdcm::SwapCode::BigEndian || swapcode == gdcm::SwapCode::BadBigEndian ) a = ( a << 8 ) | ( a >> 8 ); #else if ( swapcode == gdcm::SwapCode::LittleEndian || swapcode == gdcm::SwapCode::BadLittleEndian ) a = ( a << 8 ) | ( a >> 8 ); // On big endian as long as the SwapCode is Unknown let's pretend we were // on a LittleEndian system (might introduce overhead on those system). else if ( swapcode == SwapCode::Unknown ) a = ( a << 8 ) | ( a >> 8 ); #endif } //note: according to http://www.parashift.com/c++-faq-lite/templates.html#faq-35.8 //the inlining of the template class means that the specialization doesn't cause linker errors template inline void Swap8(T &a, SwapCode const &swapcode) { switch (swapcode) { case SwapCode::Unknown: #ifdef GDCM_WORDS_BIGENDIAN a= (( a<<24) | ((a<<8) & 0x00ff0000) | ((a>>8) & 0x0000ff00) | (a>>24) ); #endif break; case gdcm::SwapCode::LittleEndian : #ifdef GDCM_WORDS_BIGENDIAN a= (( a<<24) | ((a<<8) & 0x00ff0000) | ((a>>8) & 0x0000ff00) | (a>>24) ); #endif break; case gdcm::SwapCode::BigEndian : #ifndef GDCM_WORDS_BIGENDIAN a= (( a<<24) | ((a<<8) & 0x00ff0000) | ((a>>8) & 0x0000ff00) | (a>>24) ); #endif break; case gdcm::SwapCode::BadLittleEndian : a= ((a<<16) | (a>>16) ); break; case gdcm::SwapCode::BadBigEndian : a= (((a<< 8) & 0xff00ff00) | ((a>>8) & 0x00ff00ff) ); break; default : std::cerr << "Unexpected swap code:" << swapcode; } } template <> inline void Swap8(uint16_t &a, SwapCode const &swapcode) { switch (swapcode) { case SwapCode::Unknown: #ifdef GDCM_WORDS_BIGENDIAN a= (( a<<24) | ((a<<8) & 0x00ff0000) | ((a>>8) & 0x0000ff00) | (a>>24) ); #endif break; case gdcm::SwapCode::LittleEndian : #ifdef GDCM_WORDS_BIGENDIAN a= (( a<<24) | ((a<<8) & 0x00ff0000) | ((a>>8) & 0x0000ff00) | (a>>24) ); #endif break; case gdcm::SwapCode::BigEndian : #ifndef GDCM_WORDS_BIGENDIAN // probably not really useful since the lowest 0x0000 are what's used in unsigned shorts // a= (( a<<24) | ((a<<8) & 0x00ff0000) | ((a>>8) & 0x0000ff00) | (a>>24) ); #endif break; case gdcm::SwapCode::BadLittleEndian : //a= ((a<<16) | (a>>16) );//do nothing, a = a break; case gdcm::SwapCode::BadBigEndian : a= (uint16_t)(((a<< 8) & 0xff00) | ((a>>8) & 0x00ff) ); break; default : std::cerr << "Unexpected swap code:" << swapcode; } } } // end namespace gdcm #endif // GDCMBYTESWAP_TXX