1 /* $NetBSD: endian.h,v 1.7 2025/01/26 16:25:40 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 #pragma once 17 18 #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || \ 19 defined(__OpenBSD__) || defined(__bsdi__) 20 21 #include <sys/endian.h> 22 23 /* 24 * Recent BSDs should have [bl]e{16,32,64}toh() defined in <sys/endian.h>. 25 * Older ones might not, but these should have the alternatively named 26 * [bl]etoh{16,32,64}() functions defined. 27 */ 28 #ifndef be16toh 29 #define be16toh(x) betoh16(x) 30 #define le16toh(x) letoh16(x) 31 #define be32toh(x) betoh32(x) 32 #define le32toh(x) letoh32(x) 33 #define be64toh(x) betoh64(x) 34 #define le64toh(x) letoh64(x) 35 #endif /* !be16toh */ 36 37 #elif defined __APPLE__ 38 39 /* 40 * macOS has its own byte-swapping routines, so use these. 41 */ 42 43 #include <libkern/OSByteOrder.h> 44 45 #define htobe16(x) OSSwapHostToBigInt16(x) 46 #define htole16(x) OSSwapHostToLittleInt16(x) 47 #define be16toh(x) OSSwapBigToHostInt16(x) 48 #define le16toh(x) OSSwapLittleToHostInt16(x) 49 50 #define htobe32(x) OSSwapHostToBigInt32(x) 51 #define htole32(x) OSSwapHostToLittleInt32(x) 52 #define be32toh(x) OSSwapBigToHostInt32(x) 53 #define le32toh(x) OSSwapLittleToHostInt32(x) 54 55 #define htobe64(x) OSSwapHostToBigInt64(x) 56 #define htole64(x) OSSwapHostToLittleInt64(x) 57 #define be64toh(x) OSSwapBigToHostInt64(x) 58 #define le64toh(x) OSSwapLittleToHostInt64(x) 59 60 #elif defined(sun) || defined(__sun) || defined(__SVR4) 61 62 /* 63 * For Solaris, rely on the fallback definitions below, though use 64 * Solaris-specific versions of bswap_{16,32,64}(). 65 */ 66 67 #include <sys/byteorder.h> 68 69 #define bswap_16(x) BSWAP_16(x) 70 #define bswap_32(x) BSWAP_32(x) 71 #define bswap_64(x) BSWAP_64(x) 72 73 #elif defined(__ANDROID__) || defined(__CYGWIN__) || defined(__GNUC__) || \ 74 defined(__GNU__) 75 76 #include <byteswap.h> 77 #include <endian.h> 78 79 #else /* if defined(__DragonFly__) || defined(__FreeBSD__) || \ 80 * defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) */ 81 82 #endif /* Specific platform support */ 83 84 /* 85 * Fallback definitions. 86 */ 87 88 #include <inttypes.h> 89 90 #ifndef bswap_16 91 #define bswap_16(x) \ 92 ((uint16_t)((((uint16_t)(x) & 0xff00) >> 8) | \ 93 (((uint16_t)(x) & 0x00ff) << 8))) 94 #endif /* !bswap_16 */ 95 96 #ifndef bswap_32 97 #define bswap_32(x) \ 98 ((uint32_t)((((uint32_t)(x) & 0xff000000) >> 24) | \ 99 (((uint32_t)(x) & 0x00ff0000) >> 8) | \ 100 (((uint32_t)(x) & 0x0000ff00) << 8) | \ 101 (((uint32_t)(x) & 0x000000ff) << 24))) 102 #endif /* !bswap_32 */ 103 104 #ifndef bswap_64 105 #define bswap_64(x) \ 106 ((uint64_t)((((uint64_t)(x) & 0xff00000000000000ULL) >> 56) | \ 107 (((uint64_t)(x) & 0x00ff000000000000ULL) >> 40) | \ 108 (((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24) | \ 109 (((uint64_t)(x) & 0x000000ff00000000ULL) >> 8) | \ 110 (((uint64_t)(x) & 0x00000000ff000000ULL) << 8) | \ 111 (((uint64_t)(x) & 0x0000000000ff0000ULL) << 24) | \ 112 (((uint64_t)(x) & 0x000000000000ff00ULL) << 40) | \ 113 (((uint64_t)(x) & 0x00000000000000ffULL) << 56))) 114 #endif /* !bswap_64 */ 115 116 #ifndef htobe16 117 #if WORDS_BIGENDIAN 118 119 #define htobe16(x) (x) 120 #define htole16(x) bswap_16(x) 121 #define be16toh(x) (x) 122 #define le16toh(x) bswap_16(x) 123 124 #else /* WORDS_BIGENDIAN */ 125 126 #define htobe16(x) bswap_16(x) 127 #define htole16(x) (x) 128 #define be16toh(x) bswap_16(x) 129 #define le16toh(x) (x) 130 131 #endif /* WORDS_BIGENDIAN */ 132 #endif /* !htobe16 */ 133 134 #ifndef htobe32 135 #if WORDS_BIGENDIAN 136 137 #define htobe32(x) (x) 138 #define htole32(x) bswap_32(x) 139 #define be32toh(x) (x) 140 #define le32toh(x) bswap_32(x) 141 142 #else /* WORDS_BIGENDIAN */ 143 144 #define htobe32(x) bswap_32(x) 145 #define htole32(x) (x) 146 #define be32toh(x) bswap_32(x) 147 #define le32toh(x) (x) 148 149 #endif /* WORDS_BIGENDIAN */ 150 #endif /* !htobe32 */ 151 152 #ifndef htobe64 153 #if WORDS_BIGENDIAN 154 155 #define htobe64(x) (x) 156 #define htole64(x) bswap_64(x) 157 #define be64toh(x) (x) 158 #define le64toh(x) bswap_64(x) 159 160 #else /* WORDS_BIGENDIAN */ 161 162 #define htobe64(x) bswap_64(x) 163 #define htole64(x) (x) 164 #define be64toh(x) bswap_64(x) 165 #define le64toh(x) (x) 166 167 #endif /* WORDS_BIGENDIAN */ 168 #endif /* !htobe64 */ 169 170 /* 171 * Macros to convert uint8_t arrays to integers. 172 */ 173 174 /* Low-Endian */ 175 176 #define ISC_U16TO8_LE(p, v) \ 177 (p)[0] = (uint8_t)((v)); \ 178 (p)[1] = (uint8_t)((v) >> 8); 179 180 #define ISC_U8TO16_LE(p) (((uint16_t)((p)[0])) | ((uint16_t)((p)[1]) << 8)) 181 182 #define ISC_U32TO8_LE(p, v) \ 183 (p)[0] = (uint8_t)((v)); \ 184 (p)[1] = (uint8_t)((v) >> 8); \ 185 (p)[2] = (uint8_t)((v) >> 16); \ 186 (p)[3] = (uint8_t)((v) >> 24); 187 188 #define ISC_U8TO32_LE(p) \ 189 (((uint32_t)((p)[0])) | ((uint32_t)((p)[1]) << 8) | \ 190 ((uint32_t)((p)[2]) << 16) | ((uint32_t)((p)[3]) << 24)) 191 192 #define ISC_U48TO8_LE(p, v) \ 193 (p)[0] = (uint8_t)((v)); \ 194 (p)[1] = (uint8_t)((v) >> 8); \ 195 (p)[2] = (uint8_t)((v) >> 16); \ 196 (p)[3] = (uint8_t)((v) >> 24); \ 197 (p)[4] = (uint8_t)((v) >> 32); \ 198 (p)[5] = (uint8_t)((v) >> 40); 199 200 #define ISC_U8TO48_LE(p) \ 201 (((uint64_t)((p)[0])) | ((uint64_t)((p)[1]) << 8) | \ 202 ((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) | \ 203 ((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40)) 204 205 #define ISC_U64TO8_LE(p, v) \ 206 (p)[0] = (uint8_t)((v)); \ 207 (p)[1] = (uint8_t)((v) >> 8); \ 208 (p)[2] = (uint8_t)((v) >> 16); \ 209 (p)[3] = (uint8_t)((v) >> 24); \ 210 (p)[4] = (uint8_t)((v) >> 32); \ 211 (p)[5] = (uint8_t)((v) >> 40); \ 212 (p)[6] = (uint8_t)((v) >> 48); \ 213 (p)[7] = (uint8_t)((v) >> 56); 214 215 #define ISC_U8TO64_LE(p) \ 216 (((uint64_t)((p)[0])) | ((uint64_t)((p)[1]) << 8) | \ 217 ((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) | \ 218 ((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) | \ 219 ((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56)) 220 221 /* Big-Endian */ 222 223 #define ISC_U16TO8_BE(p, v) \ 224 (p)[0] = (uint8_t)((v) >> 8); \ 225 (p)[1] = (uint8_t)((v)); 226 227 #define ISC_U8TO16_BE(p) (((uint16_t)((p)[0]) << 8) | ((uint16_t)((p)[1]))) 228 229 #define ISC_U32TO8_BE(p, v) \ 230 (p)[0] = (uint8_t)((v) >> 24); \ 231 (p)[1] = (uint8_t)((v) >> 16); \ 232 (p)[2] = (uint8_t)((v) >> 8); \ 233 (p)[3] = (uint8_t)((v)); 234 235 #define ISC_U8TO32_BE(p) \ 236 (((uint32_t)((p)[0]) << 24) | ((uint32_t)((p)[1]) << 16) | \ 237 ((uint32_t)((p)[2]) << 8) | ((uint32_t)((p)[3]))) 238 239 #define ISC_U48TO8_BE(p, v) \ 240 (p)[0] = (uint8_t)((v) >> 40); \ 241 (p)[1] = (uint8_t)((v) >> 32); \ 242 (p)[2] = (uint8_t)((v) >> 24); \ 243 (p)[3] = (uint8_t)((v) >> 16); \ 244 (p)[4] = (uint8_t)((v) >> 8); \ 245 (p)[5] = (uint8_t)((v)); 246 247 #define ISC_U8TO48_BE(p) \ 248 (((uint64_t)((p)[0]) << 40) | ((uint64_t)((p)[1]) << 32) | \ 249 ((uint64_t)((p)[2]) << 24) | ((uint64_t)((p)[3]) << 16) | \ 250 ((uint64_t)((p)[4]) << 8) | ((uint64_t)((p)[5]))) 251 252 #define ISC_U64TO8_BE(p, v) \ 253 (p)[0] = (uint8_t)((v) >> 56); \ 254 (p)[1] = (uint8_t)((v) >> 48); \ 255 (p)[2] = (uint8_t)((v) >> 40); \ 256 (p)[3] = (uint8_t)((v) >> 32); \ 257 (p)[4] = (uint8_t)((v) >> 24); \ 258 (p)[5] = (uint8_t)((v) >> 16); \ 259 (p)[6] = (uint8_t)((v) >> 8); \ 260 (p)[7] = (uint8_t)((v)); 261 262 #define ISC_U8TO64_BE(p) \ 263 (((uint64_t)((p)[0]) << 56) | ((uint64_t)((p)[1]) << 48) | \ 264 ((uint64_t)((p)[2]) << 40) | ((uint64_t)((p)[3]) << 32) | \ 265 ((uint64_t)((p)[4]) << 24) | ((uint64_t)((p)[5]) << 16) | \ 266 ((uint64_t)((p)[6]) << 8) | ((uint64_t)((p)[7]))) 267