pendian.h (5284B)
1 #ifndef PENDIAN_H 2 #define PENDIAN_H 3 4 #ifdef __cplusplus 5 extern "C" { 6 #endif 7 8 /* 9 * Defines platform optimized (as per linux <endian.h> 10 * 11 * le16toh, le32to, le64toh, be16toh, be32toh, be64toh 12 * htole16, htole32, htole64, htobe16, htobe32, htobe64 13 * 14 * Falls back to auto-detect endian conversion which is also fast 15 * if fast byteswap operation was detected. 16 * 17 * Also defines platform optimized: 18 * 19 * bswap16, bswap32, bswap64, 20 * 21 * with fall-back to shift-or implementation. 22 * 23 * For convenience also defines: 24 * 25 * le8to, be8toh, htole8, htobe8 26 * bswap8 27 * 28 * The convience functions makes is simpler to define conversion macros 29 * based on type size. 30 * 31 * NOTE: this implementation expects arguments with no side-effects and 32 * with appropriately sized unsigned arguments. These are expected to be 33 * used with typesafe wrappers. 34 */ 35 36 #ifndef UINT8_MAX 37 #include "pstdint.h" 38 #endif 39 40 #if defined(__linux__) 41 #include <endian.h> 42 #elif defined(__OpenBSD__) || defined(__FreeBSD__) 43 #include <sys/endian.h> 44 #endif 45 46 #include "pendian_detect.h" 47 48 #if defined(_MSC_VER) 49 #if _MSC_VER >= 1300 50 #include <stdlib.h> 51 #define bswap16 _byteswap_ushort 52 #define bswap32 _byteswap_ulong 53 #define bswap64 _byteswap_uint64 54 #endif 55 #elif defined(__clang__) 56 #if __has_builtin(__builtin_bswap16) 57 #ifndef bswap16 58 #define bswap16 __builtin_bswap16 59 #endif 60 #endif 61 #if __has_builtin(__builtin_bswap32) 62 #ifndef bswap32 63 #define bswap32 __builtin_bswap32 64 #endif 65 #endif 66 #if __has_builtin(__builtin_bswap64) 67 #ifndef bswap64 68 #define bswap64 __builtin_bswap64 69 #endif 70 #endif 71 #elif defined(__OpenBSD__) || defined(__FreeBSD__) 72 #ifndef bswap16 73 #define bswap16 swap16 74 #endif 75 #ifndef bswap32 76 #define bswap32 swap32 77 #endif 78 #ifndef bswap64 79 #define bswap64 swap64 80 #endif 81 #elif defined(__GNUC__) /* Supported since at least GCC 4.4 */ 82 #ifndef bswap32 83 #define bswap32 __builtin_bswap32 84 #endif 85 #ifndef bswap64 86 #define bswap64 __builtin_bswap64 87 #endif 88 #endif 89 90 #ifndef bswap16 91 #define bswap16(v) \ 92 (((uint16_t)(v) << 8) | ((uint16_t)(v) >> 8)) 93 #endif 94 95 #ifndef bswap32 96 #define bswap32(v) \ 97 ((((uint32_t)(v) << 24)) \ 98 | (((uint32_t)(v) << 8) & UINT32_C(0x00FF0000)) \ 99 | (((uint32_t)(v) >> 8) & UINT32_C(0x0000FF00)) \ 100 | (((uint32_t)(v) >> 24))) 101 #endif 102 103 #ifndef bswap64 104 #define bswap64(v) \ 105 ((((uint64_t)(v) << 56)) \ 106 | (((uint64_t)(v) << 40) & UINT64_C(0x00FF000000000000)) \ 107 | (((uint64_t)(v) << 24) & UINT64_C(0x0000FF0000000000)) \ 108 | (((uint64_t)(v) << 8) & UINT64_C(0x000000FF00000000)) \ 109 | (((uint64_t)(v) >> 8) & UINT64_C(0x00000000FF000000)) \ 110 | (((uint64_t)(v) >> 24) & UINT64_C(0x0000000000FF0000)) \ 111 | (((uint64_t)(v) >> 40) & UINT64_C(0x000000000000FF00)) \ 112 | (((uint64_t)(v) >> 56))) 113 #endif 114 115 #ifndef bswap8 116 #define bswap8(v) ((uint8_t)(v)) 117 #endif 118 119 #if !defined(le16toh) && defined(letoh16) 120 #define le16toh letoh16 121 #define le32toh letoh32 122 #define le64toh letoh64 123 #endif 124 125 #if !defined(be16toh) && defined(betoh16) 126 #define be16toh betoh16 127 #define be32toh betoh32 128 #define be64toh betoh64 129 #endif 130 131 /* Assume it goes for all. */ 132 #if !defined(le16toh) 133 134 #if defined(__LITTLE_ENDIAN__) 135 136 #define le16toh(v) (v) 137 #define le32toh(v) (v) 138 #define le64toh(v) (v) 139 140 #define htole16(v) (v) 141 #define htole32(v) (v) 142 #define htole64(v) (v) 143 144 #define be16toh(v) bswap16(v) 145 #define be32toh(v) bswap32(v) 146 #define be64toh(v) bswap64(v) 147 148 #define htobe16(v) bswap16(v) 149 #define htobe32(v) bswap32(v) 150 #define htobe64(v) bswap64(v) 151 152 #elif defined(__BIG_ENDIAN__) 153 154 #define le16toh(v) bswap16(v) 155 #define le32toh(v) bswap32(v) 156 #define le64toh(v) bswap64(v) 157 158 #define htole16(v) bswap16(v) 159 #define htole32(v) bswap32(v) 160 #define htole64(v) bswap64(v) 161 162 #define be16toh(v) (v) 163 #define be32toh(v) (v) 164 #define be64toh(v) (v) 165 166 #define htobe16(v) (v) 167 #define htobe32(v) (v) 168 #define htobe64(v) (v) 169 170 #else 171 172 static const int __pendian_test = 1; 173 174 #define le16toh(v) (*(char *)&__pendian_test ? (v) : bswap16(v)) 175 #define le32toh(v) (*(char *)&__pendian_test ? (v) : bswap32(v)) 176 #define le64toh(v) (*(char *)&__pendian_test ? (v) : bswap64(v)) 177 178 #define htole16(v) (*(char *)&__pendian_test ? (v) : bswap16(v)) 179 #define htole32(v) (*(char *)&__pendian_test ? (v) : bswap32(v)) 180 #define htole64(v) (*(char *)&__pendian_test ? (v) : bswap64(v)) 181 182 #define be16toh(v) (*(char *)&__pendian_test ? bswap16(v) : (v)) 183 #define be32toh(v) (*(char *)&__pendian_test ? bswap32(v) : (v)) 184 #define be64toh(v) (*(char *)&__pendian_test ? bswap64(v) : (v)) 185 186 #define htobe16(v) (*(char *)&__pendian_test ? bswap16(v) : (v)) 187 #define htobe32(v) (*(char *)&__pendian_test ? bswap32(v) : (v)) 188 #define htobe64(v) (*(char *)&__pendian_test ? bswap64(v) : (v)) 189 190 #endif 191 192 #endif /* le16toh */ 193 194 /* Helpers not part of Linux <endian.h> */ 195 #if !defined(le8toh) 196 #define le8toh(n) (n) 197 #define htole8(n) (n) 198 #define be8toh(n) (n) 199 #define htobe8(n) (n) 200 #endif 201 202 #ifdef __cplusplus 203 } 204 #endif 205 206 #endif /* PENDIAN_H */