Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpEndian.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Functions for endianness handling.
32 */
33
38#include <stdexcept>
39#include <visp3/core/vpEndian.h>
40
42namespace vpEndian
43{
48uint16_t swap16bits(uint16_t val)
49{
50 const unsigned int magic_8 = 8;
51 const unsigned int magic_0x00FF = 0x00FF;
52 const unsigned int magic_0xFF00 = 0xFF00;
53 return (((val >> magic_8) & magic_0x00FF) | ((val << magic_8) & magic_0xFF00));
54}
55
60uint32_t swap32bits(uint32_t val)
61{
62 const unsigned int magic_8 = 8;
63 const unsigned int magic_24 = 24;
64 const unsigned int magic_0x000000FF = 0x000000FFU;
65 const unsigned int magic_0x0000FF00 = 0x0000FF00U;
66 const unsigned int magic_0x00FF0000 = 0x00FF0000U;
67 const unsigned int magic_0xFF000000 = 0xFF000000U;
68 return (((val >> magic_24) & magic_0x000000FF) | ((val >> magic_8) & magic_0x0000FF00) | ((val << magic_8) & magic_0x00FF0000) |
69 ((val << magic_24) & magic_0xFF000000));
70}
71
76uint64_t swap64bits(uint64_t val)
77{
78 const unsigned int magic_8 = 8;
79 const unsigned int magic_24 = 24;
80 const unsigned int magic_40 = 40;
81 const unsigned int magic_56 = 56;
82 const uint64_t magic_0x000000000000FF00 = 0x000000000000FF00;
83 const uint64_t magic_0x0000000000FF0000 = 0x0000000000FF0000;
84 const uint64_t magic_0x00000000FF000000 = 0x00000000FF000000;
85 const uint64_t magic_0x000000FF00000000 = 0x000000FF00000000;
86 const uint64_t magic_0x0000FF0000000000 = 0x0000FF0000000000;
87 const uint64_t magic_0x00FF000000000000 = 0x00FF000000000000;
88
89 // https://stackoverflow.com/a/105342
90 return (val >> magic_56) |
91 ((val << magic_40) & magic_0x00FF000000000000) |
92 ((val << magic_24) & magic_0x0000FF0000000000) |
93 ((val << magic_8) & magic_0x000000FF00000000) |
94 ((val >> magic_8) & magic_0x00000000FF000000) |
95 ((val >> magic_24) & magic_0x0000000000FF0000) |
96 ((val >> magic_40) & magic_0x000000000000FF00) |
97 (val << magic_56);
98}
99
104float swapFloat(float f)
105{
106 union
107 {
108 float f;
109 unsigned char b[4];
110 } dat1, dat2;
111
112 const unsigned int index_0 = 0;
113 const unsigned int index_1 = 1;
114 const unsigned int index_2 = 2;
115 const unsigned int index_3 = 3;
116 dat1.f = f;
117 dat2.b[index_0] = dat1.b[index_3];
118 dat2.b[index_1] = dat1.b[index_2];
119 dat2.b[index_2] = dat1.b[index_1];
120 dat2.b[index_3] = dat1.b[index_0];
121 return dat2.f;
122}
123
128double swapDouble(double d)
129{
130 union
131 {
132 double d;
133 unsigned char b[8];
134 } dat1, dat2;
135
136 const unsigned int index_0 = 0;
137 const unsigned int index_1 = 1;
138 const unsigned int index_2 = 2;
139 const unsigned int index_3 = 3;
140 const unsigned int index_4 = 4;
141 const unsigned int index_5 = 5;
142 const unsigned int index_6 = 6;
143 const unsigned int index_7 = 7;
144 dat1.d = d;
145 dat2.b[index_0] = dat1.b[index_7];
146 dat2.b[index_1] = dat1.b[index_6];
147 dat2.b[index_2] = dat1.b[index_5];
148 dat2.b[index_3] = dat1.b[index_4];
149 dat2.b[index_4] = dat1.b[index_3];
150 dat2.b[index_5] = dat1.b[index_2];
151 dat2.b[index_6] = dat1.b[index_1];
152 dat2.b[index_7] = dat1.b[index_0];
153 return dat2.d;
154}
155
161uint16_t reinterpret_cast_uchar_to_uint16_LE(unsigned char *const ptr)
162{
163#ifdef VISP_LITTLE_ENDIAN
164 return *reinterpret_cast<uint16_t *>(ptr);
165#elif defined(VISP_BIG_ENDIAN)
166 return swap16bits(*reinterpret_cast<uint16_t *>(ptr));
167#else
168 throw std::runtime_error("Not supported endianness for correct custom reinterpret_cast() function.");
169#endif
170}
171
176{
177#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
178 // https://github.com/mreininghaus/cnpypp/blob/c6cd4e2078e4f39e862720b66fb211c45577c510/src/cnpy%2B%2B.cpp#L29-L37
179 // https://stackoverflow.com/questions/1001307/detecting-endianness-programmatically-in-a-c-program
180 static_assert(sizeof(uint32_t) == 4, "uint32_t must be 4 bytes");
181
182 union
183 {
184 uint32_t i;
185 char c[4];
186 } constexpr test = { 0x01020304 };
187#else
188 union
189 {
190 uint32_t i;
191 char c[4];
192 } test = { 0x01020304 };
193#endif
194
195 return (test.c[0] == 0x01);
196}
197} // namespace vpEndian
198END_VISP_NAMESPACE
VISP_EXPORT float swapFloat(float f)
Definition vpEndian.cpp:104
VISP_EXPORT uint32_t swap32bits(uint32_t val)
Definition vpEndian.cpp:60
VISP_EXPORT uint16_t reinterpret_cast_uchar_to_uint16_LE(unsigned char *const ptr)
Definition vpEndian.cpp:161
VISP_EXPORT double swapDouble(double d)
Definition vpEndian.cpp:128
VISP_EXPORT uint64_t swap64bits(uint64_t val)
Definition vpEndian.cpp:76
VISP_EXPORT uint16_t swap16bits(uint16_t val)
Definition vpEndian.cpp:48
VISP_EXPORT bool isBigEndian()
Definition vpEndian.cpp:175