1 /*=========================================================================
2
3 Program: GDCM (Grassroots DICOM). A DICOM library
4
5 Copyright (c) 2006-2011 Mathieu Malaterre
6 All rights reserved.
7 See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
8
9 This software is distributed WITHOUT ANY WARRANTY; without even
10 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 PURPOSE. See the above copyright notice for more information.
12
13 =========================================================================*/
14 #ifndef GDCMBYTESWAP_TXX
15 #define GDCMBYTESWAP_TXX
16
17 #include "gdcmByteSwap.h"
18 #include <iostream>
19
20 #include <stdlib.h> // abort
21
22 namespace gdcm
23 {
24
25 /*
26 template (class T)
27 {
28 void bswap(inout T i)
29 {
30 byte* p = cast(byte*)&i;
31 for (int b = 0; b < T.size/2; ++b)
32 instance swap(byte).swap(p[b], p[T.size-1-b]);
33 }
34 }
35 */
36
37
38 // Machine definitions
39 #ifdef GDCM_WORDS_BIGENDIAN
40 template <class T>
SystemIsBigEndian()41 bool ByteSwap<T>::SystemIsBigEndian() { return true; }
42 template <class T>
SystemIsLittleEndian()43 bool ByteSwap<T>::SystemIsLittleEndian() { return false; }
44 #else
45 template <class T>
46 bool ByteSwap<T>::SystemIsBigEndian() { return false; }
47 template <class T>
48 bool ByteSwap<T>::SystemIsLittleEndian() { return true; }
49 #endif
50
51 template <class T>
Swap(T & p)52 void ByteSwap<T>::Swap(T &p)
53 {
54 #ifdef GDCM_WORDS_BIGENDIAN
55 ByteSwap<T>::SwapFromSwapCodeIntoSystem(p, SwapCode::LittleEndian);
56 #else
57 ByteSwap<T>::SwapFromSwapCodeIntoSystem(p, SwapCode::BigEndian);
58 #endif
59 }
60
61 // Swaps the bytes so they agree with the processor order
62 template <class T>
SwapFromSwapCodeIntoSystem(T & a,SwapCode const & swapcode)63 void ByteSwap<T>::SwapFromSwapCodeIntoSystem(T &a, SwapCode const &swapcode)
64 {
65 //std::cerr << "sizeof(T)= " << sizeof(T) << " " << (int)a << std::endl;
66 switch(sizeof(T))
67 {
68 case 1:
69 break;
70 case 2:
71 Swap4(a, swapcode);
72 break;
73 case 4:
74 Swap8(a, swapcode);
75 break;
76 default:
77 std::cerr << "Impossible" << std::endl;
78 abort();
79 }
80 }
81
82 template <class T>
SwapRange(T * p,unsigned int num)83 void ByteSwap<T>::SwapRange(T *p, unsigned int num)
84 {
85 for(unsigned int i=0; i<num; i++)
86 {
87 ByteSwap<T>::Swap(p[i]);
88 }
89 }
90
91 template <class T>
SwapRangeFromSwapCodeIntoSystem(T * p,SwapCode const & sc,std::streamoff num)92 void ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem(T *p, SwapCode const &sc,
93 std::streamoff num)
94 {
95 for( std::streamoff i=0; i<num; i++)
96 {
97 ByteSwap<T>::SwapFromSwapCodeIntoSystem(p[i], sc);
98 }
99 }
100
101 // Private:
102 //
103
104 template<class T>
Swap4(T & a,SwapCode const & swapcode)105 void Swap4(T &a, SwapCode const &swapcode)
106 {
107 #ifndef GDCM_WORDS_BIGENDIAN
108 if ( swapcode == 4321 || swapcode == 2143 )
109 a = (T)(( a << 8 ) | ( a >> 8 ));
110 #else
111 if ( swapcode == 1234 || swapcode == 3412 )
112 a = ( a << 8 ) | ( a >> 8 );
113 // On big endian as long as the SwapCode is Unknown let's pretend we were
114 // on a LittleEndian system (might introduce overhead on those system).
115 else if ( swapcode == SwapCode::Unknown )
116 a = ( a << 8 ) | ( a >> 8 );
117 #endif
118 }
119
120 //note: according to http://www.parashift.com/c++-faq-lite/templates.html#faq-35.8
121 //the inlining of the template class means that the specialization doesn't cause linker errors
122 template<class T>
Swap8(T & a,SwapCode const & swapcode)123 inline void Swap8(T &a, SwapCode const &swapcode)
124 {
125 switch (swapcode)
126 {
127 case SwapCode::Unknown:
128 #ifdef GDCM_WORDS_BIGENDIAN
129 a= (( a<<24) | ((a<<8) & 0x00ff0000) | ((a>>8) & 0x0000ff00) | (a>>24) );
130 #endif
131 break;
132 case 1234 :
133 #ifdef GDCM_WORDS_BIGENDIAN
134 a= (( a<<24) | ((a<<8) & 0x00ff0000) | ((a>>8) & 0x0000ff00) | (a>>24) );
135 #endif
136 break;
137 case 4321 :
138 #ifndef GDCM_WORDS_BIGENDIAN
139 a= (( a<<24) | ((a<<8) & 0x00ff0000) | ((a>>8) & 0x0000ff00) | (a>>24) );
140 #endif
141 break;
142 case 3412 :
143 a= ((a<<16) | (a>>16) );
144 break;
145 case 2143 :
146 a= (((a<< 8) & 0xff00ff00) | ((a>>8) & 0x00ff00ff) );
147 break;
148 default :
149 std::cerr << "Unexpected swap code:" << swapcode;
150 }
151 }
152
153 template <>
Swap8(uint16_t & a,SwapCode const & swapcode)154 inline void Swap8<uint16_t>(uint16_t &a, SwapCode const &swapcode)
155 {
156 switch (swapcode)
157 {
158 case SwapCode::Unknown:
159 #ifdef GDCM_WORDS_BIGENDIAN
160 a= (( a<<24) | ((a<<8) & 0x00ff0000) | ((a>>8) & 0x0000ff00) | (a>>24) );
161 #endif
162 break;
163 case 1234 :
164 #ifdef GDCM_WORDS_BIGENDIAN
165 a= (( a<<24) | ((a<<8) & 0x00ff0000) | ((a>>8) & 0x0000ff00) | (a>>24) );
166 #endif
167 break;
168 case 4321 :
169 #ifndef GDCM_WORDS_BIGENDIAN
170 // probably not really useful since the lowest 0x0000 are what's used in unsigned shorts
171 // a= (( a<<24) | ((a<<8) & 0x00ff0000) | ((a>>8) & 0x0000ff00) | (a>>24) );
172 #endif
173 break;
174 case 3412 :
175 //a= ((a<<16) | (a>>16) );//do nothing, a = a
176 break;
177 case 2143 :
178 a= (uint16_t)(((a<< 8) & 0xff00) | ((a>>8) & 0x00ff) );
179 break;
180 default :
181 std::cerr << "Unexpected swap code:" << swapcode;
182 }
183 }
184
185
186 } // end namespace gdcm
187
188 #endif // GDCMBYTESWAP_TXX
189