MIRA
Endian.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 by
3  * MetraLabs GmbH (MLAB), GERMANY
4  * and
5  * Neuroinformatics and Cognitive Robotics Labs (NICR) at TU Ilmenau, GERMANY
6  * All rights reserved.
7  *
8  * Contact: info@mira-project.org
9  *
10  * Commercial Usage:
11  * Licensees holding valid commercial licenses may use this file in
12  * accordance with the commercial license agreement provided with the
13  * software or, alternatively, in accordance with the terms contained in
14  * a written agreement between you and MLAB or NICR.
15  *
16  * GNU General Public License Usage:
17  * Alternatively, this file may be used under the terms of the GNU
18  * General Public License version 3.0 as published by the Free Software
19  * Foundation and appearing in the file LICENSE.GPL3 included in the
20  * packaging of this file. Please review the following information to
21  * ensure the GNU General Public License version 3.0 requirements will be
22  * met: http://www.gnu.org/copyleft/gpl.html.
23  * Alternatively you may (at your option) use any later version of the GNU
24  * General Public License if such license has been publicly approved by
25  * MLAB and NICR (or its successors, if any).
26  *
27  * IN NO EVENT SHALL "MLAB" OR "NICR" BE LIABLE TO ANY PARTY FOR DIRECT,
28  * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
29  * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF "MLAB" OR
30  * "NICR" HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * "MLAB" AND "NICR" SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
33  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
34  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
35  * ON AN "AS IS" BASIS, AND "MLAB" AND "NICR" HAVE NO OBLIGATION TO
36  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR MODIFICATIONS.
37  */
38 
47 #ifndef _MIRA_ENDIAN_H_
48 #define _MIRA_ENDIAN_H_
49 
50 #include <type_traits>
51 
52 #ifndef Q_MOC_RUN
53  #include <boost/version.hpp>
54  #if (BOOST_VERSION >= 107100)
55  // The definition has changed in boost 1.71.0
56  #include <boost/predef/other/endian.h>
57  #if BOOST_ENDIAN_LITTLE_BYTE
58  #define MIRA_LITTLE_ENDIAN
59  #undef MIRA_BIG_ENDIAN
60  #elif BOOST_ENDIAN_BIG_BYTE
61  #define MIRA_BIG_ENDIAN
62  #undef MIRA_LITTLE_ENDIAN
63  #else
64  #error "Impossible to determine the endianness of the system"
65  #endif
66  #else
67  #include <boost/detail/endian.hpp>
68  #if defined(BOOST_LITTLE_ENDIAN)
69  #define MIRA_LITTLE_ENDIAN
70  #undef MIRA_BIG_ENDIAN
71  #elif defined(BOOST_BIG_ENDIAN)
72  #define MIRA_BIG_ENDIAN
73  #undef MIRA_LITTLE_ENDIAN
74  #else
75  #error "Impossible to determine the endianness of the system"
76  #endif
77  #endif
78 #endif
79 
80 #include <platform/Types.h>
81 
82 namespace mira {
83 
85 
89 enum Endian
90 {
94 #if defined(MIRA_LITTLE_ENDIAN)
95  HOST_ENDIAN_ORDER = LITTLE_ENDIAN_ORDER
96 #elif defined(MIRA_BIG_ENDIAN)
97  HOST_ENDIAN_ORDER = BIG_ENDIAN_ORDER
98 #else
99 # error "Impossible to determine the endianness of the system"
100 #endif
101 };
102 
104 
106 namespace Private
107 {
108 
113 template<int32 size>
114 inline void swapBytes(const char* iSrc, char* oDest)
115 {
116  static_assert(size!=size, "swapBytes is not specialized for this size");
117  // size!=size forces the static assert to depend on template parameter
118  // otherwise the assert will always fail.
119 }
120 
124 template<>
125 inline void swapBytes<1>(const char* iSrc, char* oDest)
126 {
127  *oDest = *iSrc;
128 }
129 
133 template<>
134 inline void swapBytes<2>(const char* iSrc, char* oDest)
135 {
136  // Use bit manipulations instead of accessing individual bytes from memory.
137  // Much faster.
138  uint16* dest = reinterpret_cast<uint16*>(oDest);
139  const uint16* src = reinterpret_cast<const uint16*>(iSrc);
140  *dest = (*src >> 8) | (*src << 8);
141 }
142 
146 template<>
147 inline void swapBytes<4>(const char* iSrc, char* oDest)
148 {
149  // Use bit manipulations instead of accessing individual bytes from memory.
150  // Much faster.
151  uint32* dest = reinterpret_cast<uint32*>(oDest);
152  const uint32* src = reinterpret_cast<const uint32*>(iSrc);
153  *dest = (*src >> 24) |
154  ((*src & 0x00ff0000) >> 8) |
155  ((*src & 0x0000ff00) << 8) |
156  (*src << 24);
157 }
158 
162 template<>
163 inline void swapBytes<8>(const char* iSrc, char* oDest)
164 {
165  // Use bit manipulations instead of accessing individual bytes from memory.
166  // Much faster.
167  uint64* dest = reinterpret_cast<uint64*>(oDest);
168  const uint64* src = reinterpret_cast<const uint64*>(iSrc);
169  *dest = (((*src & 0xff00000000000000ull) >> 56) |
170  ((*src & 0x00ff000000000000ull) >> 40) |
171  ((*src & 0x0000ff0000000000ull) >> 24) |
172  ((*src & 0x000000ff00000000ull) >> 8) |
173  ((*src & 0x00000000ff000000ull) << 8) |
174  ((*src & 0x0000000000ff0000ull) << 24) |
175  ((*src & 0x000000000000ff00ull) << 40) |
176  ((*src & 0x00000000000000ffull) << 56));
177 }
178 
182 union IEEE754Float
183 {
184  float f;
185 
186  struct
187  {
188 #if defined(MIRA_BIG_ENDIAN)
189  uint32 negative:1;
190  uint32 exponent:8;
191  uint32 mantissa:23;
192 #elif defined(MIRA_LITTLE_ENDIAN)
193  uint32 mantissa :23;
194  uint32 exponent :8;
195  uint32 negative :1;
196 #endif
197  } ieee;
198 };
199 
203 union IEEE754Double
204 {
205  double d;
206 
207  struct
208  {
209 #if defined(MIRA_BIG_ENDIAN)
210  uint32 negative:1;
211  uint32 exponent:11;
212  uint32 mantissa0:20;
213  uint32 mantissa1:32;
214 #elif defined(MIRA_LITTLE_ENDIAN)
215  uint32 mantissa1 :32;
216  uint32 mantissa0 :20;
217  uint32 exponent :11;
218  uint32 negative :1;
219 #endif
220  } ieee;
221 };
222 
223 
224 }
225 
228 
229 
233 template <typename T>
235 {
236  typedef T Type;
237 };
238 
242 template <>
243 struct NetworkTypeTrait<float>
244 {
245  typedef uint32 Type;
246 };
247 
251 template <>
252 struct NetworkTypeTrait<double>
253 {
254  typedef uint64 Type;
255 };
256 
257 
263 template<typename T>
264 inline typename NetworkTypeTrait<T>::Type hostToNetwork(const T& value)
265 {
266  static_assert(std::is_arithmetic<T>::value,
267  "hostToNetwork accepts arithmetic types only");
268 
269 #if defined(MIRA_BIG_ENDIAN)
270  return value;
271 #else
272  T r;
273  Private::swapBytes<sizeof(T)>(reinterpret_cast<const char*>(&value),
274  reinterpret_cast<char*>(&r));
275  return r;
276 #endif
277 }
278 
282 template<>
284 {
285 #if defined(MIRA_BIG_ENDIAN)
286  return *reinterpret_cast<const NetworkTypeTrait<float>::Type*>(&value);
287 #else
288  uint32 r = 0;
289  uint8* ptr = reinterpret_cast<uint8*>(&r);
290 
291  union Private::IEEE754Float f;
292  f.f = value;
293 
294  ptr[0] = (f.ieee.negative << 7) | ((f.ieee.exponent >> 1) & 0x7F);
295  ptr[1] = ((f.ieee.exponent & 0x01) << 7) | ((f.ieee.mantissa >> 16) & 0x7F);
296  ptr[2] = (f.ieee.mantissa >> 8) & 0xFF;
297  ptr[3] = (f.ieee.mantissa) & 0xFF;
298 
299  return r;
300 #endif
301 }
302 
306 template<>
308 {
309 #if defined(MIRA_BIG_ENDIAN)
310  return *reinterpret_cast<const NetworkTypeTrait<double>::Type*>(&value);
311 #else
312  uint64 r = 0;
313  uint8* ptr = reinterpret_cast<uint8*>(&r);
314 
315  union Private::IEEE754Double d;
316  d.d = value;
317 
318  ptr[0] = (d.ieee.negative << 7) + ((d.ieee.exponent >> 4) & 0x7F);
319  ptr[1] = (((d.ieee.exponent) << 4) & 0xF0) + ((d.ieee.mantissa0 >> 16) & 0x0F);
320  ptr[2] = (d.ieee.mantissa0 >> 8) & 0xFF;
321  ptr[3] = (d.ieee.mantissa0) & 0xFF;
322  ptr[4] = (d.ieee.mantissa1 >> 24) & 0xFF;
323  ptr[5] = (d.ieee.mantissa1 >> 16) & 0xFF;
324  ptr[6] = (d.ieee.mantissa1 >> 8) & 0xFF;
325  ptr[7] = (d.ieee.mantissa1) & 0xFF;
326 
327  return r;
328 #endif
329 }
330 
336 template<typename T>
337 inline T networkToHost(const typename NetworkTypeTrait<T>::Type& value)
338 {
339  static_assert(std::is_arithmetic<T>::value,
340  "networkToHost accepts arithmetic types only");
341 
342 #if defined(MIRA_BIG_ENDIAN)
343  return value;
344 #else
345  T r;
346  Private::swapBytes<sizeof(T)>(reinterpret_cast<const char*>(&value),
347  reinterpret_cast<char*>(&r));
348  return r;
349 #endif
350 }
351 
355 template<>
357 {
358 #if defined(MIRA_BIG_ENDIAN)
359  return *reinterpret_cast<const float*>(&value);
360 #else
361  const uint8* ptr = reinterpret_cast<const uint8*>(&value);
362 
363  union Private::IEEE754Float f;
364  f.ieee.negative = ptr[0] >> 7;
365  f.ieee.exponent = ((ptr[0] << 1) & 0xFE) + ((ptr[1] >> 7) & 0x01);
366  f.ieee.mantissa = (ptr[3] & 0xFF) + ((ptr[2] << 8) & 0xFF00) +
367  (((ptr[1] & 0x7F) << 16) & 0xFF0000);
368 
369  return f.f;
370 #endif
371 }
372 
376 template<>
378 {
379 #if defined(MIRA_BIG_ENDIAN)
380  return *reinterpret_cast<const double*>(&value);
381 #else
382  const uint8* ptr = reinterpret_cast<const uint8*>(&value);
383 
384  union Private::IEEE754Double d;
385  d.ieee.negative = ptr[0] >> 7;
386  d.ieee.exponent = ((ptr[0] << 4) & 0x7F0) + ((ptr[1] >> 4) & 0x0F);
387  d.ieee.mantissa0 = (ptr[3] & 0xFF) + ((ptr[2] << 8) & 0xFF00) +
388  (((ptr[1] & 0x0F) << 16) & 0xFF0000);
389  d.ieee.mantissa1 = (ptr[7] & 0xFF) + ((ptr[6] << 8) & 0xFF00) +
390  ((ptr[5] << 16) & 0xFF0000) + ((ptr[4] << 24) & 0xFF000000);
391 
392  return d.d;
393 #endif
394 }
395 
397 
398 }
399 
400 #endif
Typedefs for OS independent basic data types.
Definition: Endian.h:91
T Type
Definition: Endian.h:236
specialize cv::DataType for our ImgPixel and inherit from cv::DataType<Vec>
Definition: IOService.h:67
Endian
Enum that specifies the endianness of the host system.
Definition: Endian.h:89
uint32 Type
Definition: Endian.h:245
uint64 Type
Definition: Endian.h:254
T networkToHost(const typename NetworkTypeTrait< T >::Type &value)
Converts a value from network byte order to host byte order.
Definition: Endian.h:337
NetworkTypeTrait< double >::Type hostToNetwork< double >(const double &value)
Specialization for double.
Definition: Endian.h:307
Definition: Endian.h:92
Definition: Endian.h:93
NetworkTypeTrait< float >::Type hostToNetwork< float >(const float &value)
Specialization for float.
Definition: Endian.h:283
NetworkTypeTrait< T >::Type hostToNetwork(const T &value)
Converts a value from host byte order to network byte order.
Definition: Endian.h:264
Trait that specifies the conversion type of a given data type.
Definition: Endian.h:234