2 * Copyright (c) 2020 nlio Authors. All Rights Reserved.
3 * Copyright 2012-2017 Nest Labs Inc. All Rights Reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
20 * This file defines macros for performing in place byte-
21 * swapping of compile-time constants via the C preprocessor as
22 * well as functions for performing byte-swapping by value and in
23 * place by pointer for 16-, 32-, and 64-bit types.
29 #include <nlio-private.h>
34 * If we are compiling under clang, GCC, or any such compatible
35 * compiler, in which -fno-builtins or -ffreestanding might be
36 * asserted, thereby eliminating built-in function optimization, we
37 * STILL want to leverage built-in bswap{16,32,64}, if available. We
38 * want this because it allows the compiler to use
39 * architecture-specific machine instructions or inline code
40 * generation to optimize an otherwise-generic and non-optimized code
41 * for byte reordering, which is exactly the kind of efficiency that
42 * would be expected of nlByteOrder.
45 #if __nlIOHasBuiltin(__builtin_bswap16)
46 #define __nlBYTEORDER_BSWAP16 __builtin_bswap16
48 #define __nlBYTEORDER_BSWAP16 nlByteOrderConstantSwap16
51 #if __nlIOHasBuiltin(__builtin_bswap32)
52 #define __nlBYTEORDER_BSWAP32 __builtin_bswap32
54 #define __nlBYTEORDER_BSWAP32 nlByteOrderConstantSwap32
57 #if __nlIOHasBuiltin(__builtin_bswap64)
58 #define __nlBYTEORDER_BSWAP64 __builtin_bswap64
60 #define __nlBYTEORDER_BSWAP64 nlByteOrderConstantSwap64
68 * @def nlByteOrderConstantSwap16
71 * Performs a preprocessor-compatible in place byte swap of the
72 * provided 16-bit value.
75 #define nlByteOrderConstantSwap16(c) \
77 ((((uint16_t)(c) & (uint16_t)0x00ffU) << 8) | \
78 (((uint16_t)(c) & (uint16_t)0xff00U) >> 8)))
81 * @def nlByteOrderConstantSwap32
84 * Performs a preprocessor-compatible in place byte swap of the
85 * provided 32-bit value.
88 #define nlByteOrderConstantSwap32(c) \
90 ((((uint32_t)(c) & (uint32_t)0x000000ffUL) << 24) | \
91 (((uint32_t)(c) & (uint32_t)0x0000ff00UL) << 8) | \
92 (((uint32_t)(c) & (uint32_t)0x00ff0000UL) >> 8) | \
93 (((uint32_t)(c) & (uint32_t)0xff000000UL) >> 24)))
96 * @def nlByteOrderConstantSwap64
99 * Performs a preprocessor-compatible in place byte swap of the
100 * provided 64-bit value.
103 #define nlByteOrderConstantSwap64(c) \
105 ((((uint64_t)(c) & (uint64_t)0x00000000000000ffULL) << 56) | \
106 (((uint64_t)(c) & (uint64_t)0x000000000000ff00ULL) << 40) | \
107 (((uint64_t)(c) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
108 (((uint64_t)(c) & (uint64_t)0x00000000ff000000ULL) << 8) | \
109 (((uint64_t)(c) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
110 (((uint64_t)(c) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
111 (((uint64_t)(c) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
112 (((uint64_t)(c) & (uint64_t)0xff00000000000000ULL) >> 56)))
115 * @def NLBYTEORDER_LITTLE_ENDIAN
118 * Constant preprocessor definition used to test #NLBYTEORDER
119 * against to determine whether the target system uses little
120 * endian byte ordering.
123 * #if NLBYTEORDER == NLBYTEORDER_LITTLE_ENDIAN
125 * Do something that is little endian byte ordering-specific.
131 #define NLBYTEORDER_LITTLE_ENDIAN 0x1234
134 * @def NLBYTEORDER_BIG_ENDIAN
137 * Constant preprocessor definition used to test #NLBYTEORDER
138 * against to determine whether the target system uses big
139 * endian byte ordering.
142 * #if NLBYTEORDER == NLBYTEORDER_BIG_ENDIAN
144 * Do something that is little endian byte ordering-specific.
150 #define NLBYTEORDER_BIG_ENDIAN 0x4321
153 * @def NLBYTEORDER_UNKNOWN_ENDIAN
156 * Constant preprocessor definition used to test #NLBYTEORDER
157 * against to determine whether the target system uses unknown
161 * #elif NLBYTEORDER == NLBYTEORDER_UNKNOWN_ENDIAN
162 * #error "Unknown byte ordering!"
167 #define NLBYTEORDER_UNKNOWN_ENDIAN 0xFFFF
173 * Constant preprocessor definition containing the target system
174 * byte ordering. May be one of:
176 * - NLBYTEORDER_BIG_ENDIAN
177 * - NLBYTEORDER_LITTLE_ENDIAN
178 * - NLBYTEORDER_UNKNOWN_ENDIAN
181 #if defined(__BYTE_ORDER__)
182 # if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
183 # define NLBYTEORDER NLBYTEORDER_LITTLE_ENDIAN
184 # elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
185 # define NLBYTEORDER NLBYTEORDER_BIG_ENDIAN
186 # endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
187 #elif defined(__LITTLE_ENDIAN__) && (__LITTLE_ENDIAN__ == 1)
188 #define NLBYTEORDER NLBYTEORDER_LITTLE_ENDIAN
189 #elif defined(__BIG_ENDIAN__) && (__BIG_ENDIAN__ == 1)
190 #define NLBYTEORDER NLBYTEORDER_BIG_ENDIAN
192 #error "Endianness undefined!"
193 #define NLBYTEORDER NLBYTEORDER_UNKNOWN_ENDIAN
194 #endif /* defined(__BYTE_ORDER__) */
197 nlByteOrderUnknown = NLBYTEORDER_UNKNOWN_ENDIAN,
198 nlByteOrderLittleEndian = NLBYTEORDER_LITTLE_ENDIAN,
199 nlByteOrderBigEndian = NLBYTEORDER_BIG_ENDIAN
203 * This represents a type for a byte ordering.
205 typedef uint16_t nlByteOrder;
208 * This returns the byte order of the current system.
210 * @return The byte order of the current system.
212 static inline nlByteOrder nlByteOrderGetCurrent(void)
214 #if (NLBYTEORDER == NLBYTEORDER_LITTLE_ENDIAN)
215 return nlByteOrderLittleEndian;
216 #elif (NLBYTEORDER == NLBYTEORDER_BIG_ENDIAN)
217 return nlByteOrderBigEndian;
219 return nlByteOrderUnknown;
224 * This unconditionally performs a byte order swap by value of the
225 * specified 16-bit value.
227 * @param[in] inValue The 16-bit value to be byte order swapped.
229 * @return The input value, byte order swapped.
231 static inline uint16_t nlByteOrderValueSwap16(uint16_t inValue)
233 return __nlBYTEORDER_BSWAP16(inValue);
237 * This unconditionally performs a byte order swap by value of the
238 * specified 32-bit value.
240 * @param[in] inValue The 32-bit value to be byte order swapped.
242 * @return The input value, byte order swapped.
244 static inline uint32_t nlByteOrderValueSwap32(uint32_t inValue)
246 return __nlBYTEORDER_BSWAP32(inValue);
250 * This unconditionally performs a byte order swap by value of the
251 * specified 64-bit value.
253 * @param[in] inValue The 64-bit value to be byte order swapped.
255 * @return The input value, byte order swapped.
257 static inline uint64_t nlByteOrderValueSwap64(uint64_t inValue)
259 return __nlBYTEORDER_BSWAP64(inValue);
263 * This unconditionally performs a byte order swap by pointer in place
264 * of the specified 16-bit value.
266 * @warning The input value is assumed to be on a natural alignment
267 * boundary for the target system. It is the responsibility of the
268 * caller to perform any necessary alignment to avoid system faults
269 * for systems that do not support unaligned accesses.
271 * @param[inout] inValue A pointer to the 16-bit value to be byte
274 static inline void nlByteOrderPointerSwap16(uint16_t *inValue)
276 *inValue = nlByteOrderValueSwap16(*inValue);
280 * This unconditionally performs a byte order swap by pointer in place
281 * of the specified 32-bit value.
283 * @warning The input value is assumed to be on a natural alignment
284 * boundary for the target system. It is the responsibility of the
285 * caller to perform any necessary alignment to avoid system faults
286 * for systems that do not support unaligned accesses.
288 * @param[inout] inValue A pointer to the 32-bit value to be byte
291 static inline void nlByteOrderPointerSwap32(uint32_t *inValue)
293 *inValue = nlByteOrderValueSwap32(*inValue);
297 * This unconditionally performs a byte order swap by pointer in place
298 * of the specified 64-bit value.
300 * @warning The input value is assumed to be on a natural alignment
301 * boundary for the target system. It is the responsibility of the
302 * caller to perform any necessary alignment to avoid system faults
303 * for systems that do not support unaligned accesses.
305 * @param[inout] inValue A pointer to the 64-bit value to be byte
308 static inline void nlByteOrderPointerSwap64(uint64_t *inValue)
310 *inValue = nlByteOrderValueSwap64(*inValue);
313 #if (NLBYTEORDER == NLBYTEORDER_LITTLE_ENDIAN)
314 #include <nlbyteorder-little.h>
315 #elif (NLBYTEORDER == NLBYTEORDER_BIG_ENDIAN)
316 #include <nlbyteorder-big.h>
317 #endif /* (NLBYTEORDER == NLBYTEORDER_LITTLE_ENDIAN) */
323 #undef __nlBYTEORDER_BSWAP16
324 #undef __nlBYTEORDER_BSWAP32
325 #undef __nlBYTEORDER_BSWAP64
327 #endif /* NLBYTEORDER_H */