MRPT  2.0.4
reverse_bytes.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2020, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "core-precomp.h" // Precompiled headers
11 
13 #include <cstdlib>
14 #include <cstring>
15 
16 // These #defines from:
17 // https://github.com/boostorg/endian/blob/master/include/boost/endian/detail/intrinsic.hpp
18 #ifndef __has_builtin
19 #define __has_builtin(x) 0 // Compatibility with non-clang compilers
20 #endif
21 #if ( \
22  defined(__clang__) && __has_builtin(__builtin_bswap32) && \
23  __has_builtin(__builtin_bswap64)) || \
24  (defined(__GNUC__) && \
25  (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
26 #define HAVE_BSWAP_INTRINSICS
27 #endif
28 
29 template <typename T>
30 void reverseBytesInPlace_2b(T& v_in_out)
31 {
32  uint16_t org;
34  &org, &v_in_out,
35  sizeof(T)); // Was: = *reinterpret_cast<uint16_t*>(&v_in_out); but
36  // caused SIGBUS in some archs
37  const uint16_t val_rev = ((org & 0xff00) >> 8) | ((org & 0x00ff) << 8);
38  std::memcpy(&v_in_out, &val_rev, sizeof(T)); // This avoid deref. puned
39  // pointer warning with:
40  // *reinterpret_cast<const
41  // T*>(&val_rev);
42 }
43 
44 template <typename T>
45 void reverseBytesInPlace_4b(T& v_in_out)
46 {
47  uint32_t org;
49  &org, &v_in_out,
50  sizeof(T)); // Was: = = *reinterpret_cast<uint32_t*>(&v_in_out); but
51  // caused SIGBUS in some archs
52  const uint32_t val_rev =
53 #if defined(_MSC_VER)
54  _byteswap_ulong(org);
55 #elif defined(HAVE_BSWAP_INTRINSICS)
56  __builtin_bswap32(org);
57 #else
58  ((org & 0xff000000) >> (3 * 8)) | ((org & 0x00ff0000) >> (1 * 8)) |
59  ((org & 0x0000ff00) << (1 * 8)) | ((org & 0x000000ff) << (3 * 8));
60 #endif
61  std::memcpy(&v_in_out, &val_rev, sizeof(T)); // This avoid deref. puned
62  // pointer warning with:
63  // *reinterpret_cast<const
64  // T*>(&val_rev);
65 }
66 
67 template <typename T>
68 void reverseBytesInPlace_8b(T& v_in_out)
69 {
70  uint64_t org;
72  &org, &v_in_out,
73  sizeof(T)); // Was: = *reinterpret_cast<uint64_t*>(&v_in_out); but
74 // caused SIGBUS in some archs
75 #if defined(_MSC_VER)
76  uint64_t val_rev = _byteswap_uint64(org);
77 #elif defined(HAVE_BSWAP_INTRINSICS)
78  uint64_t val_rev = __builtin_bswap64(org);
79 #else
80  uint64_t val_rev = 0;
81  int i, j;
82  for (i = 7, j = 7; i >= 4; i--, j -= 2)
83  val_rev |= ((org & (UINT64_C(0xff) << (i * 8))) >> (j * 8));
84  for (i = 3, j = 1; i >= 0; i--, j += 2)
85  val_rev |= ((org & (UINT64_C(0xff) << (i * 8))) << (j * 8));
86 #endif
87  std::memcpy(&v_in_out, &val_rev, sizeof(T)); // This avoid deref. puned
88  // pointer warning with:
89  // *reinterpret_cast<const
90  // T*>(&val_rev);
91 }
92 
94 {
95  // Nothing to do.
96 }
97 
98 void mrpt::reverseBytesInPlace(uint8_t& /*v_in_out*/)
99 {
100  // Nothing to do.
101 }
102 void mrpt::reverseBytesInPlace(int8_t& /*v_in_out*/)
103 {
104  // Nothing to do.
105 }
106 
107 void mrpt::reverseBytesInPlace(uint16_t& v_in_out)
108 {
109  reverseBytesInPlace_2b(v_in_out);
110 }
111 
112 void mrpt::reverseBytesInPlace(int16_t& v_in_out)
113 {
114  reverseBytesInPlace_2b(v_in_out);
115 }
116 
117 void mrpt::reverseBytesInPlace(uint32_t& v_in_out)
118 {
119  reverseBytesInPlace_4b(v_in_out);
120 }
121 
122 void mrpt::reverseBytesInPlace(int32_t& v_in_out)
123 {
124  reverseBytesInPlace_4b(v_in_out);
125 }
126 
127 void mrpt::reverseBytesInPlace(uint64_t& v_in_out)
128 {
129  reverseBytesInPlace_8b(v_in_out);
130 }
131 
132 void mrpt::reverseBytesInPlace(int64_t& v_in_out)
133 {
134  reverseBytesInPlace_8b(v_in_out);
135 }
136 
137 void mrpt::reverseBytesInPlace(float& v_in_out)
138 {
139  reverseBytesInPlace_4b(v_in_out);
140 }
141 
142 void mrpt::reverseBytesInPlace(double& v_in_out)
143 {
144  reverseBytesInPlace_8b(v_in_out);
145 }
146 
147 void mrpt::reverseBytesInPlace(std::chrono::time_point<mrpt::Clock>& v_in_out)
148 {
149  int64_t val = v_in_out.time_since_epoch().count();
151  v_in_out = std::chrono::time_point<mrpt::Clock>(mrpt::Clock::duration(val));
152 }
153 
154 #ifdef HAVE_LONG_DOUBLE
155 void mrpt::reverseBytesInPlace(long double& v_in_out)
156 {
157  uint64_t dat[2];
158  std::memcpy(
159  &dat[0], &v_in_out, sizeof(long double)); // This avoid deref. puned
160  // pointer warning with:
161  // *reinterpret_cast<const
162  // T*>(&val_rev);
163  std::swap(dat[0], dat[1]);
164  reverseBytesInPlace(dat[0]);
165  reverseBytesInPlace(dat[1]);
166  std::memcpy(&v_in_out, &dat[0], sizeof(long double));
167 }
168 #endif
std::chrono::duration< rep, period > duration
Definition: Clock.h:24
void reverseBytesInPlace_4b(T &v_in_out)
void reverseBytesInPlace_8b(T &v_in_out)
void reverseBytesInPlace(bool &v_in_out)
Reverse the order of the bytes of a given type (useful for transforming btw little/big endian) ...
int val
Definition: mrpt_jpeglib.h:957
void reverseBytesInPlace_2b(T &v_in_out)
void memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) noexcept
An OS and compiler independent version of "memcpy".



Page generated by Doxygen 1.8.14 for MRPT 2.0.4 Git: 33de1d0ad Sat Jun 20 11:02:42 2020 +0200 at sáb jun 20 17:35:17 CEST 2020