Home | History | Annotate | Line # | Download | only in isc
      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