libtins 4.5
Loading...
Searching...
No Matches
endianness.h
1/*
2 * Copyright (c) 2017, Matias Fontanini
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30#ifndef TINS_ENDIANNESS_H
31#define TINS_ENDIANNESS_H
32
33#include <stdint.h>
34#include <tins/macros.h>
35
36#if defined(__APPLE__)
37 #include <sys/types.h>
38 #define TINS_IS_LITTLE_ENDIAN (BYTE_ORDER == LITTLE_ENDIAN)
39 #define TINS_IS_BIG_ENDIAN (BYTE_ORDER == BIG_ENDIAN)
40#elif defined(BSD)
41 #include <sys/endian.h>
42 #define TINS_IS_LITTLE_ENDIAN (_BYTE_ORDER == _LITTLE_ENDIAN)
43 #define TINS_IS_BIG_ENDIAN (_BYTE_ORDER == _BIG_ENDIAN)
44#elif defined(_WIN32)
45 #include <cstdlib>
46 // Assume windows == little endian. fixme later
47 #define TINS_IS_LITTLE_ENDIAN 1
48 #define TINS_IS_BIG_ENDIAN 0
49#else
50 #include <endian.h>
51 #define TINS_IS_LITTLE_ENDIAN (__BYTE_ORDER == __LITTLE_ENDIAN)
52 #define TINS_IS_BIG_ENDIAN (__BYTE_ORDER == __BIG_ENDIAN)
53#endif
54
55// Define macros to swap bytes using compiler intrinsics when possible
56#if defined(_MSC_VER)
57 #define TINS_BYTE_SWAP_16(data) _byteswap_ushort(data)
58 #define TINS_BYTE_SWAP_32(data) _byteswap_ulong(data)
59 #define TINS_BYTE_SWAP_64(data) _byteswap_uint64(data)
60#elif defined(TINS_HAVE_GCC_BUILTIN_SWAP)
61 #define TINS_BYTE_SWAP_16(data) __builtin_bswap16(data)
62 #define TINS_BYTE_SWAP_32(data) __builtin_bswap32(data)
63 #define TINS_BYTE_SWAP_64(data) __builtin_bswap64(data)
64#else
65 #define TINS_NO_BYTE_SWAP_INTRINSICS
66#endif
67
68namespace Tins {
69namespace Endian {
70
77inline uint8_t do_change_endian(uint8_t data) {
78 return data;
79}
80
86inline uint16_t do_change_endian(uint16_t data) {
87 #ifdef TINS_NO_BYTE_SWAP_INTRINSICS
88 return ((data & 0xff00) >> 8) | ((data & 0x00ff) << 8);
89 #else
90 return TINS_BYTE_SWAP_16(data);
91 #endif
92}
93
99inline uint32_t do_change_endian(uint32_t data) {
100 #ifdef TINS_NO_BYTE_SWAP_INTRINSICS
101 return (((data & 0xff000000) >> 24) | ((data & 0x00ff0000) >> 8) |
102 ((data & 0x0000ff00) << 8) | ((data & 0x000000ff) << 24));
103 #else
104 return TINS_BYTE_SWAP_32(data);
105 #endif
106}
107
113 inline uint64_t do_change_endian(uint64_t data) {
114 #ifdef TINS_NO_BYTE_SWAP_INTRINSICS
115 return (((uint64_t)(do_change_endian((uint32_t)(data & 0xffffffff))) << 32) |
116 (do_change_endian(((uint32_t)(data >> 32)))));
117 #else
118 return TINS_BYTE_SWAP_64(data);
119 #endif
120 }
121
126// Helpers to convert
127template<typename T>
128struct conversion_dispatch_helper {
129 static T dispatch(T data) {
130 return do_change_endian(data);
131 }
132};
133
134
135template<size_t>
136struct conversion_dispatcher;
137
138template<>
139struct conversion_dispatcher<sizeof(uint8_t)>
140: public conversion_dispatch_helper<uint8_t> { };
141
142template<>
143struct conversion_dispatcher<sizeof(uint16_t)>
144: public conversion_dispatch_helper<uint16_t> { };
145
146template<>
147struct conversion_dispatcher<sizeof(uint32_t)>
148: public conversion_dispatch_helper<uint32_t> { };
149
150template<>
151struct conversion_dispatcher<sizeof(uint64_t)>
152: public conversion_dispatch_helper<uint64_t> { };
153
165 template<typename T>
166 inline T change_endian(T data) {
167 return conversion_dispatcher<sizeof(T)>::dispatch(data);
168 }
169
170#if TINS_IS_LITTLE_ENDIAN
176 template<typename T>
177 inline T host_to_be(T data) {
178 return change_endian(data);
179 }
180
188 template<typename T>
189 inline T host_to_le(T data) {
190 return data;
191 }
192
198 template<typename T>
199 inline T be_to_host(T data) {
200 return change_endian(data);
201 }
202
208 template<typename T>
209 inline T le_to_host(T data) {
210 return data;
211 }
212#elif TINS_IS_BIG_ENDIAN
218 template<typename T>
219 inline T host_to_be(T data) {
220 return data;
221 }
222
230 template<typename T>
231 inline T host_to_le(T data) {
232 return change_endian(data);
233 }
234
240 template<typename T>
241 inline T be_to_host(T data) {
242 return data;
243 }
244
250 template<typename T>
251 inline T le_to_host(T data) {
252 return change_endian(data);
253 }
254#endif
255
256} // Endian
257} // Tins
258
259#endif // TINS_ENDIANNESS_H
The Tins namespace.
Definition address_range.h:38