foobar2000 SDK  2015-01-14
byte_order_helper.h
Go to the documentation of this file.
1 #ifndef _PFC_BYTE_ORDER_HELPER_
2 #define _PFC_BYTE_ORDER_HELPER_
3 
4 namespace pfc {
5  void byteswap_raw(void * p_buffer,t_size p_bytes);
6 
7  template<typename T> T byteswap_t(T p_source);
8 
9  template<> inline char byteswap_t<char>(char p_source) {return p_source;}
10  template<> inline unsigned char byteswap_t<unsigned char>(unsigned char p_source) {return p_source;}
11  template<> inline signed char byteswap_t<signed char>(signed char p_source) {return p_source;}
12 
13  template<typename T> T byteswap_int_t(T p_source) {
14  enum { width = sizeof(T) };
15  typedef typename sized_int_t<width>::t_unsigned tU;
16  tU in = p_source, out = 0;
17  for(unsigned walk = 0; walk < width; ++walk) {
18  out |= ((in >> (walk * 8)) & 0xFF) << ((width - 1 - walk) * 8);
19  }
20  return out;
21  }
22 
23 #ifdef _MSC_VER//does this even help with performance/size?
24  template<> inline wchar_t byteswap_t<wchar_t>(wchar_t p_source) {return _byteswap_ushort(p_source);}
25 
26  template<> inline short byteswap_t<short>(short p_source) {return _byteswap_ushort(p_source);}
27  template<> inline unsigned short byteswap_t<unsigned short>(unsigned short p_source) {return _byteswap_ushort(p_source);}
28 
29  template<> inline int byteswap_t<int>(int p_source) {return _byteswap_ulong(p_source);}
30  template<> inline unsigned int byteswap_t<unsigned int>(unsigned int p_source) {return _byteswap_ulong(p_source);}
31 
32  template<> inline long byteswap_t<long>(long p_source) {return _byteswap_ulong(p_source);}
33  template<> inline unsigned long byteswap_t<unsigned long>(unsigned long p_source) {return _byteswap_ulong(p_source);}
34 
35  template<> inline long long byteswap_t<long long>(long long p_source) {return _byteswap_uint64(p_source);}
36  template<> inline unsigned long long byteswap_t<unsigned long long>(unsigned long long p_source) {return _byteswap_uint64(p_source);}
37 #else
38  template<> inline wchar_t byteswap_t<wchar_t>(wchar_t p_source) {return byteswap_int_t(p_source);}
39 
40  template<> inline short byteswap_t<short>(short p_source) {return byteswap_int_t(p_source);}
41  template<> inline unsigned short byteswap_t<unsigned short>(unsigned short p_source) {return byteswap_int_t(p_source);}
42 
43  template<> inline int byteswap_t<int>(int p_source) {return byteswap_int_t(p_source);}
44  template<> inline unsigned int byteswap_t<unsigned int>(unsigned int p_source) {return byteswap_int_t(p_source);}
45 
46  template<> inline long byteswap_t<long>(long p_source) {return byteswap_int_t(p_source);}
47  template<> inline unsigned long byteswap_t<unsigned long>(unsigned long p_source) {return byteswap_int_t(p_source);}
48 
49  template<> inline long long byteswap_t<long long>(long long p_source) {return byteswap_int_t(p_source);}
50  template<> inline unsigned long long byteswap_t<unsigned long long>(unsigned long long p_source) {return byteswap_int_t(p_source);}
51 #endif
52 
53  template<> inline float byteswap_t<float>(float p_source) {
54  float ret;
55  *(t_uint32*) &ret = byteswap_t(*(const t_uint32*)&p_source );
56  return ret;
57  }
58 
59  template<> inline double byteswap_t<double>(double p_source) {
60  double ret;
61  *(t_uint64*) &ret = byteswap_t(*(const t_uint64*)&p_source );
62  return ret;
63  }
64 
65  //blargh at GUID byteswap issue
66  template<> inline GUID byteswap_t<GUID>(GUID p_guid) {
67  GUID ret;
68  ret.Data1 = pfc::byteswap_t(p_guid.Data1);
69  ret.Data2 = pfc::byteswap_t(p_guid.Data2);
70  ret.Data3 = pfc::byteswap_t(p_guid.Data3);
71  ret.Data4[0] = p_guid.Data4[0];
72  ret.Data4[1] = p_guid.Data4[1];
73  ret.Data4[2] = p_guid.Data4[2];
74  ret.Data4[3] = p_guid.Data4[3];
75  ret.Data4[4] = p_guid.Data4[4];
76  ret.Data4[5] = p_guid.Data4[5];
77  ret.Data4[6] = p_guid.Data4[6];
78  ret.Data4[7] = p_guid.Data4[7];
79  return ret;
80  }
81 
82 
83 
84 };
85 
86 #ifdef _MSC_VER
87 
88 #if defined(_M_IX86) || defined(_M_X64)
89 #define PFC_BYTE_ORDER_IS_BIG_ENDIAN 0
90 #endif
91 
92 #else//_MSC_VER
93 
94 #if defined(__APPLE__)
95 #include <architecture/byte_order.h>
96 #else
97 #include <endian.h>
98 #endif
99 
100 #if __BYTE_ORDER == __LITTLE_ENDIAN
101 #define PFC_BYTE_ORDER_IS_BIG_ENDIAN 0
102 #else
103 #define PFC_BYTE_ORDER_IS_BIG_ENDIAN 1
104 #endif
105 
106 #endif//_MSC_VER
107 
108 #ifdef PFC_BYTE_ORDER_IS_BIG_ENDIAN
109 #define PFC_BYTE_ORDER_IS_LITTLE_ENDIAN (!(PFC_BYTE_ORDER_IS_BIG_ENDIAN))
110 #else
111 #error please update byte order #defines
112 #endif
113 
114 
115 namespace pfc {
116  static const bool byte_order_is_big_endian = !!PFC_BYTE_ORDER_IS_BIG_ENDIAN;
117  static const bool byte_order_is_little_endian = !!PFC_BYTE_ORDER_IS_LITTLE_ENDIAN;
118 
119  template<typename T> T byteswap_if_be_t(T p_param) {return byte_order_is_big_endian ? byteswap_t(p_param) : p_param;}
120  template<typename T> T byteswap_if_le_t(T p_param) {return byte_order_is_little_endian ? byteswap_t(p_param) : p_param;}
121 }
122 
123 namespace byte_order {
124 
125 #if PFC_BYTE_ORDER_IS_BIG_ENDIAN//big endian
126  template<typename T> inline void order_native_to_le_t(T& param) {param = pfc::byteswap_t(param);}
127  template<typename T> inline void order_native_to_be_t(T& param) {}
128  template<typename T> inline void order_le_to_native_t(T& param) {param = pfc::byteswap_t(param);}
129  template<typename T> inline void order_be_to_native_t(T& param) {}
130 #else//little endian
131  template<typename T> inline void order_native_to_le_t(T& param) {}
132  template<typename T> inline void order_native_to_be_t(T& param) {param = pfc::byteswap_t(param);}
133  template<typename T> inline void order_le_to_native_t(T& param) {}
134  template<typename T> inline void order_be_to_native_t(T& param) {param = pfc::byteswap_t(param);}
135 #endif
136 };
137 
138 
139 
140 namespace pfc {
141  template<typename TInt,unsigned width,bool IsBigEndian>
143  public:
144  inline static void Run(TInt p_value,t_uint8 * p_out) {
145  *p_out = (t_uint8)(p_value);
146  __EncodeIntHelper<TInt,width-1,IsBigEndian>::Run(p_value >> 8,p_out + (IsBigEndian ? -1 : 1));
147  }
148  };
149 
150  template<typename TInt,bool IsBigEndian>
151  class __EncodeIntHelper<TInt,1,IsBigEndian> {
152  public:
153  inline static void Run(TInt p_value,t_uint8* p_out) {
154  *p_out = (t_uint8)(p_value);
155  }
156  };
157  template<typename TInt,bool IsBigEndian>
158  class __EncodeIntHelper<TInt,0,IsBigEndian> {
159  public:
160  inline static void Run(TInt,t_uint8*) {}
161  };
162 
163  template<typename TInt>
164  inline void encode_little_endian(t_uint8 * p_buffer,TInt p_value) {
166  }
167  template<typename TInt>
168  inline void encode_big_endian(t_uint8 * p_buffer,TInt p_value) {
169  __EncodeIntHelper<TInt,sizeof(TInt),true>::Run(p_value,p_buffer + (sizeof(TInt) - 1));
170  }
171 
172 
173  template<typename TInt,unsigned width,bool IsBigEndian>
175  public:
176  inline static TInt Run(const t_uint8 * p_in) {
177  return (__DecodeIntHelper<TInt,width-1,IsBigEndian>::Run(p_in + (IsBigEndian ? -1 : 1)) << 8) + *p_in;
178  }
179  };
180 
181  template<typename TInt,bool IsBigEndian>
182  class __DecodeIntHelper<TInt,1,IsBigEndian> {
183  public:
184  inline static TInt Run(const t_uint8* p_in) {return *p_in;}
185  };
186 
187  template<typename TInt,bool IsBigEndian>
188  class __DecodeIntHelper<TInt,0,IsBigEndian> {
189  public:
190  inline static TInt Run(const t_uint8*) {return 0;}
191  };
192 
193  template<typename TInt>
194  inline void decode_little_endian(TInt & p_out,const t_uint8 * p_buffer) {
196  }
197 
198  template<typename TInt>
199  inline void decode_big_endian(TInt & p_out,const t_uint8 * p_buffer) {
200  p_out = __DecodeIntHelper<TInt,sizeof(TInt),true>::Run(p_buffer + (sizeof(TInt) - 1));
201  }
202 
203  template<typename TInt>
204  inline TInt decode_little_endian(const t_uint8 * p_buffer) {
205  TInt temp;
206  decode_little_endian(temp,p_buffer);
207  return temp;
208  }
209 
210  template<typename TInt>
211  inline TInt decode_big_endian(const t_uint8 * p_buffer) {
212  TInt temp;
213  decode_big_endian(temp,p_buffer);
214  return temp;
215  }
216 
217  template<bool IsBigEndian,typename TInt>
218  inline void decode_endian(TInt & p_out,const t_uint8 * p_buffer) {
219  if (IsBigEndian) decode_big_endian(p_out,p_buffer);
220  else decode_little_endian(p_out,p_buffer);
221  }
222  template<bool IsBigEndian,typename TInt>
223  inline void encode_endian(t_uint8 * p_buffer,TInt p_in) {
224  if (IsBigEndian) encode_big_endian(p_in,p_buffer);
225  else encode_little_endian(p_in,p_buffer);
226  }
227 
228 
229 
230  template<unsigned width>
231  inline void reverse_bytes(t_uint8 * p_buffer) {
232  pfc::swap_t(p_buffer[0],p_buffer[width-1]);
233  reverse_bytes<width-2>(p_buffer+1);
234  }
235 
236  template<> inline void reverse_bytes<1>(t_uint8 * p_buffer) { }
237  template<> inline void reverse_bytes<0>(t_uint8 * p_buffer) { }
238 
239 }
240 
241 
242 
243 #endif
wchar_t byteswap_t< wchar_t >(wchar_t p_source)
uint8_t t_uint8
Definition: int_types.h:9
int byteswap_t< int >(int p_source)
void encode_little_endian(t_uint8 *p_buffer, TInt p_value)
Definition: pfc.h:53
static const bool byte_order_is_little_endian
void reverse_bytes< 1 >(t_uint8 *p_buffer)
void byteswap_raw(void *p_buffer, t_size p_bytes)
Definition: other.cpp:114
uint64_t t_uint64
Definition: int_types.h:3
T byteswap_if_le_t(T p_param)
uint8_t Data4[8]
Definition: pfc.h:57
void reverse_bytes< 0 >(t_uint8 *p_buffer)
signed char byteswap_t< signed char >(signed char p_source)
uint16_t Data3
Definition: pfc.h:56
void decode_big_endian(TInt &p_out, const t_uint8 *p_buffer)
T byteswap_t(T p_source)
void order_native_to_le_t(T &param)
double byteswap_t< double >(double p_source)
void decode_little_endian(TInt &p_out, const t_uint8 *p_buffer)
static const bool byte_order_is_big_endian
void order_be_to_native_t(T &param)
unsigned short byteswap_t< unsigned short >(unsigned short p_source)
short byteswap_t< short >(short p_source)
unsigned char byteswap_t< unsigned char >(unsigned char p_source)
static void Run(TInt p_value, t_uint8 *p_out)
void reverse_bytes(t_uint8 *p_buffer)
void order_le_to_native_t(T &param)
static TInt Run(const t_uint8 *p_in)
size_t t_size
Definition: int_types.h:48
char byteswap_t< char >(char p_source)
unsigned long long byteswap_t< unsigned long long >(unsigned long long p_source)
long long byteswap_t< long long >(long long p_source)
void encode_endian(t_uint8 *p_buffer, TInt p_in)
static void Run(TInt p_value, t_uint8 *p_out)
void encode_big_endian(t_uint8 *p_buffer, TInt p_value)
unsigned int byteswap_t< unsigned int >(unsigned int p_source)
void decode_endian(TInt &p_out, const t_uint8 *p_buffer)
T byteswap_int_t(T p_source)
unsigned long byteswap_t< unsigned long >(unsigned long p_source)
uint16_t Data2
Definition: pfc.h:55
long byteswap_t< long >(long p_source)
GUID byteswap_t< GUID >(GUID p_guid)
void swap_t(T &p_item1, T &p_item2)
Definition: primitives.h:285
float byteswap_t< float >(float p_source)
uint32_t Data1
Definition: pfc.h:54
T byteswap_if_be_t(T p_param)
uint32_t t_uint32
Definition: int_types.h:5
void order_native_to_be_t(T &param)